为什么当我在Perl中从自身中减去相同的浮点数时,我没有得到零?[复制]

Why don't I get zero when I subtract the same floating point number from itself in Perl? [duplicate]

提问人:Prashant 提问时间:1/17/2010 最后编辑:CommunityPrashant 更新时间:1/18/2010 访问量:2998

问:

这个问题在这里已经有答案了:
13年前关闭。

可能的重复项:
为什么 C# 中的浮点运算不精确?
为什么 ghci 说 1.1 + 1.1 + 1.1 > 3.3 是真的?

#!/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.

难道不应该是零吗???? 谁能解释一下......

perl 浮点 精度

评论

3赞 Ether 1/18/2010
什么,你不认为 0.0000000000000201655014354845 足够接近零吗?
0赞 ysth 1/18/2010
这个问题并不完全是引用的非 perl 问题的重复,因为 perl 提供的默认字符串化精度略低于可用的数值精度,因此问题变得复杂。

答:

7赞 CB Bailey 1/17/2010 #1

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

为什么它应该是零?0.579787 != 0.579788 和 0.433273 != 0.433272。这些可能都没有精确的浮点表示,因此您应该预料到一些不准确之处。

19赞 Vinko Vrsalovic 1/17/2010 #2

每个计算机科学家都应该了解的浮点运算知识

请参阅为什么 C# 中的浮点运算不精确?

这与Perl无关,但与浮点有关。

3赞 FalseVinylShrub 1/17/2010 #3

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

它所展示的是,您可以创建 2 个不同的浮点数 ( 和 ),它们在打印出来时看起来相同,但内部有微小的差异。如果你不小心,这些差异可能会被放大。$val1$val2

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

4赞 brian d foy 1/18/2010 #4

perlfaq4为什么我得到长小数(例如,19.9499999999999)而不是我应该得到的数字(例如,19.95)的回答?


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

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

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

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

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

评论

0赞 ysth 1/18/2010
这是 perlfaq 的另一面;请参阅我对问题的评论。