FreePascal中Max函数的意外结果

时间:2018-08-25 18:29:31

标签: delphi 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函数不仅会从两个参数返回较大的数字,还会更改其值。

在上面的示例代码中,fValueMax的期望值正好是fValue,但是fValueMax更大。差异大约为E-7,虽然很小,但仍然出乎意料,这使我的以下代码崩溃(此处未发布该代码,以使问题更清楚和简单)。

1 个答案:

答案 0 :(得分:10)

我应该预先声明,我上次使用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并将其分配给您与分配给{{1 }},当然,它的值看起来与您在fValue中返回的值非常接近。

因此,最后,我没有使用fValueMax和文字Max来调用fValue,而是使用了两个0类型的变量来调用它,其中一个已设置为double。在这种情况下,您可以看到输入(0.0)和输出(fValue2)具有完全相同的值。因此,尽管我不确切知道用​​于确定要调用的重载的Pascal规则是什么,但我不知道您最初对fValueMax2的调用是否以某种方式解析为采用两个Max值并返回相同值的版本

尽管您可能知道这一点,但我还是不得不提起通常的警告,如singlesingle这样的浮点类型将无法始终准确地代表您的值希望他们这样做。 Here's a good overview.