Perl转换为int错误但只有特定的数字

时间:2011-08-15 15:09:28

标签: perl floating-point integer

以下perl代码将浮点数转换为错误的整数

use strict;

my $zahl =297607.22000;
$zahl=$zahl * 100;
print "$zahl\n";
my $text=sprintf ("%017d",$zahl);
print $text;

这个输出是:

29760722
00000000029760721

问题是,您可以将给定的数字更改为其他数字并且有效。

知道这里有什么问题,或者Perl做错了吗?

感谢您的帮助!

4 个答案:

答案 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

intsprintf %d截断小数,因此最终得到29760721. printsprintf %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将禁用浮点数。