FreePascal中Max函数的意外结果

skr*_*rat 2 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.   
Run Code Online (Sandbox Code Playgroud)

然而,结果完全出乎意料.出于某种原因,Max函数不仅返回两个参数中的较大数字,还会更改其值.

在上面的示例代码中,fValueMax的预期值恰好是fValue,而fValueMax则更大.差异大约是E-7,如此之小,但仍然出乎意料并且崩溃了我的下面的代码(这里没有公布这个问题以保持问题的清晰和简单).

Joe*_*ell 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.
Run Code Online (Sandbox Code Playgroud)

我的前两个writeln命令显示您报告的相同结果.我怀疑可能Max会返回一个精度较低的值,double你希望得到的值,所以我创建fSingle并分配了与你指定的相同的文字fValue,当然,它的值看起来非常接近你要回来的fValueMax.

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

虽然您可能已经意识到这一点,但我觉得有必要抛出关于浮点类型如何single并且double不能始终能够准确表示您希望它们的值的通常谨慎.这是一个很好的概述.

  • FWIW:荣誉.从没有触及Pascal 25年的人那里,你的代码看起来仍然很好.<G> (3认同)
  • 看起来确实是FreePascal中的一个错误(它似乎选择单精度重载,即使第二个参数是双精度).当为第一个参数指定0.0而不是0时,它会选择正确的重载. (2认同)