如果我有变量a,b,类型为double的c,设c:= a / b,并给出a和b值为7和10,则c的值为0.7,寄存器小于0.70。
另一方面,如果变量都是类型扩展的,则c的值0.7不会注册为小于0.70。
这看起来很奇怪。我错过了哪些信息?
答案 0 :(得分:18)
首先,需要注意Delphi中的float文字是Extended类型。因此,当您将double与文字进行比较时,double可能首先“扩展”为Extended,然后进行比较。 (编辑:仅在32位应用程序中才是这样。在64位应用程序中,Extended
是别名Double
)
此处将显示所有ShowMessage。
procedure DoSomething;
var
A, B : Double;
begin
A := 7/10;
B := 0.7; //Here, we lower the precision of "0.7" to double
//Here, A is expanded to Extended... But it has already lost precision. This is (kind of) similar to doing Round(0.7) <> 0.7
if A <> 0.7 then
ShowMessage('Weird');
if A = B then //Here it would work correctly.
ShowMessage('Ok...');
//Still... the best way to go...
if SameValue(A, 0.7, 0.0001) then
ShowMessage('That will never fails you');
end;
这里有一些文献给你
What Every Computer Scientist Should Know About Floating-Point Arithmetic
答案 1 :(得分:11)
二进制浮点数学数字0.7
没有表示。你的陈述在最近c
的{{1}}中进行计算,根据你的说法,我没有检查,它略低于0.7。
显然,在扩展精度中,最接近的浮点数为0.7略高于它。但仍然没有确切的代表0.7。二进制浮点中没有任何精度。
根据经验,任何非最后一个非零小数不是5的非整数不能完全表示为二进制浮点数(反之亦然:0.05也不能完全表示)。< / p>
答案 2 :(得分:8)
它与您正在使用的两种不同浮点类型中的精度位数有关,以及无论精度如何都无法准确表示大量数字的事实。 (从纯数学方面来看:无理数超过有理数)
以2/3为例。它'不能用十进制表示。有4位有效数字,它表示为0.6667。有8位有效数字,当前为0.66666667。 尾随7是综合反映,反映下一个数字将是> 5如果有空间保留它。
0.6667大于0.66666667,因此计算机将评估2/3(4位)&gt; 2/3(8位数)。
在双重和扩展变量中你的.7 vs .70也是如此。
要避免此特定问题,请尝试在整个代码中使用相同的数字类型。一般使用浮点数时,有很多小事需要注意。最大的不是编写代码来比较两个浮点数是否相等 - 即使它们应该是相同的值,计算中有许多因素会使它们最终变得非常微小。您需要测试两个数字之间的差异是非常小的,而不是比较相等性。差异有多小取决于你和计算的本质,它通常被称为epsilon,取自微积分定理和证明。
答案 3 :(得分:5)
你错过了This Thing。
请参阅“准确性问题”一章。另见Pascal的答案。
为了在不使用Extended
类型的情况下修复代码,您必须添加Math
单元并使用专门为此目的而构建的SameValue
函数。
在您的情况下使用SameValue时,请务必使用不同于0的Epsilon
值。
例如:
var
a, b, c: double;
begin
a:=7; b:=10;
c:=a/b;
if SameValue(c, 0.70, 0.001) then
ShowMessage('Ok')
else
ShowMessage('Wrong!');
end;
HTH
答案 4 :(得分:1)
看看这篇关于Delphi和浮点数的优秀文章 - 它应该解释一下:http://rvelthuis.de/articles/articles-floats.html