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 一样。
虽然您可能已经意识到这一点,但我还是不得不提醒大家注意,像 single
和 double
这样的浮点类型并不总是能够准确地表示您希望他们拥有的价值观。 Here's a good overview.
运行这个例子很容易理解:
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 一样。
虽然您可能已经意识到这一点,但我还是不得不提醒大家注意,像 single
和 double
这样的浮点类型并不总是能够准确地表示您希望他们拥有的价值观。 Here's a good overview.