由于浮点数,我在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
中显示,因此在值15上使用了floor
? $a
和$c
的比较让我感到非常困惑......
我读过this但无法弄明白。我还找到了sprintf
的解决方法,在我看来并不是很方便。
答案 0 :(得分:4)
尝试:
printf "%.18g\n", my $a=(($x1-$x0)/$dx);
你所看到的15并不完全是15;它可能会少一点或多一点。 大多数浮点数只能不精确地表示;当在操作中使用时,效果是错误的,乘以。
经典参考:http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
使用sprintf的解决方法通常不太好用,因为它只处理非常少量的不精确。最好检查一下你的计算并决定你应该使用什么样的公差,并在铺地之前添加它。
答案 1 :(得分:2)
在双精度中,$ dx的值恰好是
33.33333333333333570180911920033395290374755859375
($ x1- $ x0)/ $ dx的值恰好是
14.9999999999999982236431605997495353221893310546875
floor($ x1- $ x0)/ $ dx因此是14。
你从print / sprintf得到15,因为打印四舍五入值(除非你要求更多的数字,比如"%。17g")。