Perl错误地转换为int,但仅使用特定的数字

Perl错误地转换为int,但仅使用特定的数字,perl,floating-point,integer,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只是做错了吗 谢谢你的帮助 这与常见问题相关()$

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

use strict;

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

29760722
00000000029760721
问题是,您可以将给定的数字更改为其他数字,并且它可以工作

你知道这里出了什么问题吗?或者Perl只是做错了吗


谢谢你的帮助

这与常见问题相关()
$zahl
未正确舍入,它向下舍入到下一个较低的整数。

当您将浮点乘法100时,结果类似于
29760721.999999963
。然后,当您将
%d
转换为整数时,它将被截断为
29760721


试试sprintf('%.10f',$zahl),你应该能够看到这一点。

你必须非常小心使用浮点数,并将它们视为定点。由于内置中可能发生各种转换,有时一个整数转换可能与另一个整数转换不完全相同。对于
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源代码,以了解具体的转换差异在哪里


我建议,如果您要使用定点数字,请将它们全部转换为整数(使用通用转换函数,最好将源数字视为字符串),然后在
使用整数下使用它们
pragma,它将禁用浮点数。

22/100
是二进制的周期数,就像1/3是十进制的周期数一样。将其精确存储在浮点数中需要无限的存储空间

$ perl -e'$_="297607.22000"; $_*=100; printf "%.20f\n", $_'
29760721.99999999627470970154
int
sprintf%d
截断小数,最后得到29760721
print
sprintf%f
round,这样您就可以得到想要的结果

$ perl -e'$_="297607.22000"; $_*=100; printf "%017.0f\n", $_'
00000000029760722

为什么在这两个例子中舍入不同?@Mat:因为int向零舍入,而最接近297607.22000的浮点表示恰好类似于297607。21999999997@ysth当前位置我理解这是一个取整问题。我不明白的是为什么对第一个
print
语句和
sprintf
中的四舍五入应用不同的规则。
print
将值打印为实数,因此在底层表示精度有限的情况下,它可以打印出最精确的值。显然它是通过四舍五入来实现的。当您
printf
一个带有
%d”
的实数时,它首先将其从浮点转换为整数,然后该转换将被截断。请尝试
printf“%f%d\n”,1.9,1.9
。Mat:这本身不是取整问题,而是表示问题。297607.22不是可表示的浮点数;最接近它的浮点数将小于或大于它。如果小于,乘以100将得到一个略小于预期整数的数字;如果更多,则会稍微多一些。如果小于,int()/%d将为您提供与预期不同的数字,如果大于,int()/%d将“起作用”。但无论哪种情况,int都是向零舍入的;事实上,它甚至与Perl无关。这是浮点数的一个属性,所有使用浮点数的语言都会表现出相同的行为。它一点也不舍入。它只是被截断了。您有
int
截断和舍入。它只会截断。@cjm,拼写错误<代码>打印需要更好的公关代理!(双关语)在我注意到你的信息之前就修复了:)