tao*_*oxl 2 delphi floating-point floating-point-precision
我正在使用FloatToText这种方式:
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;
Run Code Online (Sandbox Code Playgroud)
如果我传递给这个函数值9229.99,它返回一个字符串值9229.9900000000016,但它不是我想要的.当我创建一个新项目并在那里复制上面的代码时,它运行良好.它返回9229.99.
他们在不同项目中工作的原因可能是什么?
这实际上是一个可表示性的问题.这是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.
Run Code Online (Sandbox Code Playgroud)
产量
9229.98999999999978 9229.99
你要18位数.将值存储为双精度时,存储的值将变为不精确到18位十进制精度.双精度值具有15-16个精确的十进制小数位数.并且该值小于18.当您将值存储为扩展值时,可用的精度更高,足以将您的值精确存储到您请求的精度的18位十进制数字.
我总是在这件事上提到Rob Kennedy的精彩页面:http://pages.cs.wisc.edu/~rkennedy/exact-float?number = 9229.99
这告诉我们,当转换为extended和double时,您的值表示为:
9229.99 = + 9229.99000 00000 00000 21316 28207 28030 05576 13372 80273 4375 9229.99 = + 9229.98999 99999 99781 72127 15744 97222 90039 0625
这与上面的输出完全吻合.
所以,我希望您会发现在现有项目中,您将在某个时刻将值存储到双精度变量中.那时你会失去额外的精确度Extended.
对于它的价值,我认为80位扩展类型是不合时宜的.它仅支持英特尔芯片,仅供32位编译器使用.根据我的经验,它提供了超过双精度的任何真正的好处.由于内存对齐,其性能很差.作为很多浮点代码的作者,我从不使用扩展.