当我在Perl中从自身中减去相同的浮点数时,为什么不能得到零?

时间:2010-01-17 10:09:51

标签: perl floating-point floating-accuracy

  

可能重复:
  Why is floating point arithmetic in C# imprecise?
  Why does ghci say that 1.1 + 1.1 + 1.1 > 3.3 is True?

#!/usr/bin/perl
$l1 = "0+0.590580+0.583742+0.579787+0.564928+0.504538+0.459805+0.433273+0.384211+0.3035810";
$l2 = "0+0.590580+0.583742+0.579788+0.564928+0.504538+0.459805+0.433272+0.384211+0.3035810";
$val1 = eval ($l1);
$val2 = eval ($l2);
$diff = (($val1 - $val2)/$val1)*100;
print " (($val1 - $val2)/$val1)*100 ==> $diff\n";

令人惊讶的是输出结束了

((4.404445 - 4.404445)/4.404445)*100 ==> -2.01655014354845e-14.

不应该是ZERO ???? 任何人都可以解释一下......

4 个答案:

答案 0 :(得分:18)

答案 1 :(得分:7)

它非常接近于零,这正是我所期待的。

为什么它应该为零? 0.579787!= 0.579788和0.433273!= 0.433272。可能没有一个具有精确的浮点表示,所以你应该期待一些不准确。

答案 2 :(得分:4)

perlfaq4回答Why am I getting long decimals (eg, 19.9499999999999) instead of the numbers I should be getting (eg, 19.95)?


在内部,您的计算机代表二进制的浮点数。数字(如两个权力)计算机无法准确存储所有数字。一些实数在此过程中会失去精确度。这是计算机如何存储数字并影响所有计算机语言的问题,而不仅仅是Perl。

perlnumber显示数字表示和转换的血腥细节。

要限制数字中的小数位数,可以使用printf或sprintf函数。有关详细信息,请参阅“浮点运算”。

printf "%.2f", 10/3;

my $number = sprintf "%.2f", 10/3;

答案 3 :(得分:3)

当您将两个字符串更改为相等时($l1$l2之间有两个不同的数字),它确实会导致零。

它的证明是你可以创建2个不同的浮点数($val1$val2),这些浮点数在打印时看起来相同,但内部差别很小。如果你不小心,这些差异可以放大。

Vinko Vrsalovic发布了一些很好的链接来解释原因。

相关问题