以下perl代码将浮点数转换为错误的整数
use strict;
my $zahl =297607.22000;
$zahl=$zahl * 100;
print "$zahl\n";
my $text=sprintf ("%017d",$zahl);
print $text;
这个输出是:
29760722
00000000029760721
问题是,您可以将给定的数字更改为其他数字并且有效。
知道这里有什么问题,或者Perl做错了吗?
感谢您的帮助!
答案 0 :(得分:8)
这与常见问题解答(Why am I getting long decimals)有关。 $zahl
未正确舍入,它向下舍入到下一个较低的整数。
答案 1 :(得分:2)
当您将浮点乘法乘以100时,结果将类似于29760721.9999999963
。然后,当您将%d
转换为整数时,会将其截断为29760721
。
尝试sprintf('%.10f', $zahl)
,您应该能够看到这一点。
答案 2 :(得分:2)
22/100
是二进制的周期数,就像1/3是十进制的周期数一样。它需要无限存储才能将其精确存储在浮点数中。
$ perl -e'$_="297607.22000"; $_*=100; printf "%.20f\n", $_'
29760721.99999999627470970154
int
和sprintf %d
截断小数,因此最终得到29760721. print
和sprintf %f
,这样您就可以获得所需的结果。
$ perl -e'$_="297607.22000"; $_*=100; printf "%017.0f\n", $_'
00000000029760722
答案 3 :(得分:1)
你必须非常小心浮点数并将它们视为固定点。由于内置中可能发生的各种转换,有时可能一个整数转换与另一个完全转换不完全相同。似乎这种情况多次出现x.22
个数字:
use strict;
my $n = 0;
for (0 .. 10_000_000) {
my $float = 100 * "$_.22";
my $str = "$float";
my $int = int $float;
if ($str ne $int) {
$n++;
#say "$float, $str, $int";
}
}
say "n = $n";
打印
n = 76269
在我的系统上。
仔细查看Perl源代码,可以看到确切的转换差异在哪里。
我建议如果您要使用定点数,将它们全部转换为整数(使用常见的转换函数,最好将源数字视为字符串),然后使用它们全部在use integer;
pragma将禁用浮点数。