This is in fact an issue of representability. Here's the SSCCE:
{$APPTYPE CONSOLE}
uses
SysUtils, Windows;
function ExFloatToStr(Value: Extended): string;
var
Buffer: array[0..63] of Char;
FormatSettings: TFormatSettings;
begin
GetLocaleFormatSettings(GetUserDefaultLCID, FormatSettings);
SetString(Result, Buffer, FloatToText(Buffer, Value, fvExtended, ffGeneral,
18, 0, FormatSettings));
end;
var
X: Double;
Y: Extended;
begin
X := 9229.99;
Y := 9229.99;
Writeln(ExFloatToStr(X));
Writeln(ExFloatToStr(Y));
Readln;
end.
Output
9229.98999999999978
9229.99
You ask for 18 digits. When you store the value as a double precision, the value stored becomes imprecise to 18 decimal digit precision. A double precision value has 15-16 significant decimal digits of precision. And that is fewer than 18. When you store the value as an extended value, there is more precision available, sufficient to store your value accurately to the 18 decimal digits of precision that your requested.
I always refer to Rob Kennedy's excellent page on this matter: http://pages.cs.wisc.edu/~rkennedy/exact-float?number=9229.99
This tells us that your value, when converted to extended and double is represented as:
9229.99 = + 9229.99000 00000 00000 21316 28207 28030 05576 13372 80273 4375
9229.99 = + 9229.98999 99999 99781 72127 15744 97222 90039 0625
And this tallies precisely with the output above.
So, I expect that you will find that in your existing project you will, at some point, be storing the value to a double precision variable. And at that point you lose the extra precision of Extended
.
For what it is worth, I regard the 80 bit extended type as an anachronism. It is only supported on Intel chips, and only used by 32 bit compilers. In my experience it nevers offers any real benefit over double precision. And its performance is poor because of memory alignment. As the author of a lot of floating point code, I never use extended.