德尔福数学:为什么0.7 <0.70?

时间:2010-05-02 17:13:16

标签: delphi math comparison floating-point types

如果我有变量a,b,类型为double的c,设c:= a / b,并给出a和b值为7和10,则c的值为0.7,寄存器小于0.70。

另一方面,如果变量都是类型扩展的,则c的值0.7不会注册为小于0.70。

这看起来很奇怪。我错过了哪些信息?

5 个答案:

答案 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