1

由于浮点数,我在 Perl (v5.10.1) 中的计算遇到了一些问题:

#!/usr/bin/perl
use strict;
use warnings;
use POSIX;

my $x1 = 1500;
my $x0 = 1000;
my $dx = 100/3;

print "($x1-$x0)/$dx \n";                                   #(1500-1000)/33.3333333333333
print my $a=(($x1-$x0)/$dx), "\n";                          #15
print my $b=floor(($x1-$x0)/$dx), "\n";                     #14
print my $c=floor($a), "\n";                                #14
print floor(15), "\n";                                      #15
print my $d=floor(sprintf("%.0f", ($x1-$x0)/$dx)), "\n";    #15

为什么有时输出 14?值 15 不是按它显示的那样保存$a并因此用于floor值 15 吗?$a和的对比$c真的让我很疑惑……

我读了这个,但无法弄清楚。sprintf我还发现了在我看来不是很方便的解决方法。

4

2 回答 2

4

尝试:

printf "%.18g\n", my $a=(($x1-$x0)/$dx);

你看到的 15 并不完全是 15。它可能会少一点或多一点。大多数浮点数只能不精确地表示;在操作中使用时,效果是错误的,成倍增加。

经典参考:http ://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

sprintf 的解决方法通常不太好用,因为它只处理非常少量的不精确性。最好检查您的计算并确定您应该使用的公差并在铺地板之前添加它。

于 2013-11-04T15:57:28.897 回答
2

在双精度中,$dx 的值正好是

33.33333333333333570180911920033395290374755859375

($x1-$x0)/$dx 的值正好是

14.9999999999999982236431605997495353221893310546875

因此 floor($x1-$x0)/$dx 为 14。

您从 print/sprintf 得到 15,因为打印会四舍五入十进制值(除非您要求更多数字,例如“%.17g”)。

于 2013-11-05T02:32:26.010 回答