浮点双精度常量被视为扩展

Floating Point double constants treated as extended

在 664 位应用程序中,如果我将浮点常量与从 StrToFloat() 获得的相同“值”的值进行比较,我会得到不同的结果。例如:

procedure foo;
const
  d1 = 0.6694716
  d3: double = 0.6694716
var
  d2: double;
begin
  d2 := StrToFloat('0.6694716');
  if d1 = d2 then
    beep;
  if d1 = d3 then
    beep;
  if d2 = d3 then
    beep;

end;

d1 和 d3 的十六进制值为 $B47339B4,而 d2 的十六进制值为 $B47339B3。虽然他们是“平等”的比较。它们在技术上是不一样的。据我所知,常数 d1 和 d2 是错误的。也许编译器使用了 FPU,这是由于四舍五入造成的?

缺少将我所有的常量作为字符串并在 运行 时转换它们。有人知道解决这个问题的方法吗?

Delphi 中的浮点文字默认是扩展的。在 64 位中,这应该没有任何区别,但在 32 位中却有区别。我的猜测是解析器仍然在内部将浮点文字表示为 10 字节浮点数(扩展),然后 64 位编译器在编译时将其“向下舍入”为 8 字节(双精度)。

如果我的假设是正确的,那么可能没有什么可以避免的。

编辑

Delphi 进行以下转换

  • 双精度 (3FE56C4FB47339B3) 转换为扩展 (3FFFEAB627DA399CD9800)
  • 双精度 (3FE56C4FB47339B4) 转换为扩展 (3FFFEAB627DA399CDA000)
  • 0.6694716 已扩展(3FFFEAB627DA399CD9C00)

令人厌恶的是,我将常量作为字符串值并在单元初始化中将它们转换为双精度值。这样我们就得到了 double 而不是扩展数学。这似乎有效。我预计它不适用于 32 位。

function HexToDouble(const val: uint64): double; inline;
begin
  result := Pdouble(@val)^;
end;

//use
D1 := HexToDouble(fe56c4fb47339b3);