我有一个for循环,我希望每次增加0.1的变量,但是值的变化与增量不同,我不确定为什么。
我已经简化了for循环,它仍然提供了一个奇怪的输出:
for (my $t = 1000; $t < 1500 ;$t+=0.1) {
print "$t\n";
}
打印:
1034.9
1035
1035.1
1035.2
1035.3
1035.4
1035.49999999999
1035.59999999999
1035.69999999999
1035.79999999999
1035.89999999999
1035.99999999999
1036.09999999999
1036.19999999999
1036.29999999999
[it then goes on like this to 1500]
我不知道小数位的来源。这是我对Perl理解的问题吗?
提前致谢。
答案 0 :(得分:9)
1/10是二进制的周期数,如1/3是十进制的。它不能完全表示为浮点数。
$ perl -e'printf "%.20g\n", 0.1'
0.10000000000000001
永远不要在不涉及容差的情况下将浮动指针编号与另一个浮动指针编号进行比较,并警惕错误累积。
这里使用整数进行算术的简单解决方案,并在需要时生成浮点数
for (my $tx10 = 10000; $tx10 < 15000; ++$tx10) {
my $t = $tx10/10;
print "$t\n";
}
简化为
for my $tx10 (10000..14999) {
my $t = $tx10/10;
print "$t\n";
}
____ ____ ____
0.1 = 0.00011 0.4 = 0.0110 0.7 = 0.10110
____ ____
0.2 = 0.0011 0.5 = 0.1 0.8 = 0.11001
____ ____ ____
0.3 = 0.01001 0.6 = 0.1001 0.9 = 0.11100
答案 1 :(得分:2)
for (my $t = 1000; $t < 1500 ;$t+=.1) {
printf("%.1f\n", $t);
}
答案 2 :(得分:1)
替代:
for (10000..14999) {
my $t = $_/10;
print "$t\n";
}
由于无法在二进制文件中精确指定0.1,因此舍入错误将在代码中累积。在这个答案中,金额始终保持足够精确,以便perl的内部数字到字符串舍入将显示正确的数字。课程:尽可能使用整数。
答案 3 :(得分:0)
测试条件
perl -le 'for (my $t = 1000.0; $t < 1500.0 ;$t+=0.1) { print $t}'| perl -n -e '($a)=/(\d$)/; print "fail $a $b $_" if ($a eq $b); $b=$a'
另一种解决方法
perl -le 'for (my $t = 1000.0; $t < 1500.0 ;$t+=0.1) { $t=sprintf("%.1f", $t); print $t}'| perl -n -e '($a)=/(\d$)/; print "fail $a $b $_" if ($a eq $b); $b=$a'