我以这种方式使用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;


如果我将此函数值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.


输出量

9229.98999999999978
9229.99


您要求输入18位数字。当您将值存储为双精度时,存储的值将不精确到18位十进制数字精度。双精度值的精度为15-16个有效十进制数字。并且小于18。当您将值存储为扩展值时,可以使用的精度更高,足以将您的值精确存储为所需的18位小数位数。

在这件事上,我总是指罗伯·肯尼迪的精彩网页:http://pages.cs.wisc.edu/~rkennedy/exact-float?number=9229.99

这告诉我们,您的值在转换为扩展和双精度时表示为:

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位扩展类型是不合时宜的。它仅在Intel芯片上受支持,并且仅由32位编译器使用。以我的经验,它永远不会比双精度提供任何真正的好处。由于内存对齐,其性能很差。作为很多浮点代码的作者,我从不使用扩展。

关于delphi - 为什么FloatToText在不同的项目中返回不同的值?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22063157/

10-12 12:57
查看更多