gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-03 14:34:39 27 4
gpt4 key购买 nike

在短暂查看 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/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com