FreePascal 中 Max 函数的意外结果

Unexpected result from Max function in FreePascal

运行这个例子很容易理解:

program Project1;

uses
SysUtils, Math;

var
  fValue: double;
  fValueMax: double;
begin
  fValue := 7.0207503445953527;
  fValueMax := Max(0, fValue);
  writeln(fValue);
  writeln(fValueMax);
  readln;
end.   

然而结果完全出乎意料。出于某种原因,Max 函数不仅 return 来自两个参数的较大数字,而且还会更改它的值。

在上面的示例代码中,fValueMax 的期望值恰好是 fValue,但 fValueMax 更大。差异大约是 E-7,如此之小,但仍然出乎意料并使我的以下代码崩溃(为了使问题简单明了,此处未发布)。

我应该提前声明,我上次使用 Pascal 是将近 25 年前的事了。但是出于好奇我下载了 Free Pascal 并尝试了这个:

program Project1;

uses
SysUtils, Math;

var
  fValue: double;
  fValueMax: double;

  fSingle: single;

  fValue2: double;
  fValue2b: double;
  fValueMax2: double;

begin
  fValue := 7.0207503445953527; 
  fSingle := 7.0207503445953527;
  fValueMax := Max(0, fValue);

  writeln(fValue);       // prints 7.0207503445953527E+000
  writeln(fValueMax);    // prints 7.0207505226135254E+000

  writeln(fSingle);      // prints 7.020750523E+00

  fValue2 := 7.0207503445953527;
  fValue2b := 0.0;
  fValueMax2 := Max(fValue2b, fValue2);

  writeln(fValue2);      // prints 7.0207503445953527E+000
  writeln(fValueMax2);   // prints 7.0207503445953527E+000
  readln;
end.

我的前两个 writeln 命令显示的结果与您报告的结果相同。我怀疑 Max 返回的值可能比您期望返回的 double 精度低,因此我创建了 fSingle 并为其分配了与分配给 [=15 相同的文字=],果然,它的值看起来非常接近您在 fValueMax 中得到的值。

所以最后,我没有用 fValue 和文字 0 调用 Max,而是用两个 double 类型的变量来调用它,其中一个我有设置为 0.0。在这种情况下,您可以看到输入 (fValue2) 和输出 (fValueMax2) 具有完全相同的值。因此,虽然我不确切知道 Pascal 用于确定要调用哪个重载的规则是什么,但我想知道您对 Max 的原始调用是否以某种方式解析为采用两个 single 值和 returns 一样。

虽然您可能已经意识到这一点,但我还是不得不提醒大家注意,像 singledouble 这样的浮点类型并不总是能够准确地表示您希望他们拥有的价值观。 Here's a good overview.