Delphi Tokyo 64 位将非正规数刷新为零?

标签 delphi floating-point

在短暂查看 system.math 的源代码时,我发现 64 位版本 Delphi Tokyo 10.2.3 将非正规 IEEE-Doubles 刷新为零,从以下程序中可以看出;

{$apptype console}
uses
  system.sysutils, system.math;
var
  x: double;
const
  twopm1030 : UInt64 = $0000100000000000; {2^(-1030)}
begin
  x := PDouble(@twopm1030)^;
  writeln(x);
  x := ldexp(1,-515);
  writeln(x*x);
  x := ldexp(1,-1030);
  writeln(x);
end.

对于 32 位,输出符合预期

8.69169475979376E-0311
8.69169475979376E-0311
8.69169475979376E-0311

但是对于 64 位我得到

 8.69169475979375E-0311
 0.00000000000000E+0000
 0.00000000000000E+0000

所以基本上东京可以在 64 位模式下处理非正规数,常量写入正确,但是从算术运算甚至使用 ldexp 时,非正规结果会被刷新为零。

这个观察结果可以在其他系统上得到证实吗?如果有,记录在哪里? (我能找到的关于零冲洗的唯一信息是, 存储在 Real48 中时非正规数变为零)。

更新:我知道两者 32 位和 64 位都使用单一重载。对于 32 位,使用 x87 FPU,并且所有精度(单精度、 double 、扩展精度)的 ASM 代码实际上都是相同的。 FPU 始终返回 80 位扩展,该扩展存储在 double 型中,而不会提前截断。 64位代码在存储前进行了精度调整。 同时,我提交了一份问题报告 ( https://quality.embarcadero.com/browse/RSP-20925 ),重点关注 32 位或 64 位的不一致结果。

最佳答案

更新:

仅编译器处理重载选择的方式有所不同。

@Graymatter 发现,对于 32 位和 64 位编译器,调用的 LdExp 重载都是 Single 类型。唯一的区别是代码库,其中 32 位编译器使用 asm 代码,而 64 位编译器具有 purepascal 实现。

要修复代码以使用正确的重载,请显式定义 LdExp() 第一个参数的类型,如下所示(64 位):

program Project116;

{$APPTYPE CONSOLE}
uses
  system.sysutils, system.math;
var
  x: double;
const
  twopm1030 : UInt64 = $0000100000000000; {2^(-1030)}
begin
  x := PDouble(@twopm1030)^;
  writeln(x);
  x := ldexp(Double(1),-515);
  writeln(x*x);
  x := ldexp(Double(1),-1030);
  writeln(x);
  ReadLn;
end. 

输出:

 8.69169475979375E-0311
 8.69169475979375E-0311
 8.69169475979375E-0311
<小时/>

我想说,这种行为应该被报告为 RTL bug,,因为在您的情况下选择的重载函数是 Single 类型。生成的类型是 Double ,编译器肯定应该相应地进行调整。 因为 32 位和 64 位编译器应该产生相同的结果。

<小时/>

注意,浮点类型的 Double(1) 类型转换是在 Delphi 10.2 Tokyo 中引入的。之前版本的解决方案参见What is first version of Delphi which allows typecasts like double(10)

关于Delphi Tokyo 64 位将非正规数刷新为零?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51445586/

相关文章:

delphi - 将大量字符串添加到 TStringList 时出现问题

math - 处理 Go 算术中的 float 精度?

c - C中的冒泡排序 float

c - 无法将 float 传递给另一个函数?

python 2.5 : how to convert float to hex?

python - 垫 python float

delphi - 我的插入语句中出现语法错误

delphi - Delphi 中透明光标显示错误颜色

delphi - 带有 LiveBindings 的自定义网格 - EBindCompError 'No list control editor available'

delphi - 如何将Tiff图像与Delphi合并?