如何消除Perl舍入错误

Use*_*er1 3 perl rounding

考虑以下程序:

$x=12345678901.234567000;
$y=($x-int($x))*1000000000;
printf("%f:%f\n",$x,$y);
Run Code Online (Sandbox Code Playgroud)

这是什么是印刷品:

12345678901.234568:234567642.211914

我在期待:

12345678901.234567:234567000

这似乎是Perl中的某种舍入问题.
我怎么能改变它来234567000取而代之?
我做错什么了吗?

Gre*_*con 6

这是一个经常被问到的问题.

为什么我得到长小数(例如,19.9499999999999)而不是我应该得到的数字(例如,19.95)?

在内部,您的计算机代表二进制的浮点数.数字(如两个权力)计算机无法准确存储所有数字.一些实数在此过程中会失去精确度.这是计算机如何存储数字并影响所有计算机语言的问题,而不仅仅是Perl.

perlnumber显示数字表示和转换的血淋淋的细节.要限制数字中的小数位数,可以使用printfsprintf功能.有关更多详细信息,请参阅浮点算法.

printf "%.2f", 10/3;
my $number = sprintf "%.2f", 10/3;
Run Code Online (Sandbox Code Playgroud)


jro*_*way 5

制作"使用bignum ;" 你的程序的第一行.

其他答案解释了使用浮点运算时会发生什么 - 到最后的一些数字实际上并不是答案的一部分.这是为了使计算能够在合理的时间和空间内完成.如果你愿意使用无限的时间和空间来处理数字,那么你可以使用任意精度的数字和数学,这就是"使用bignum"所启用的.它更慢并且使用更多的内存,但它的工作方式就像你在小学时学到的数学一样.

通常,在将程序转换为任意精度数学之前,最好了解浮点数学的工作原理.它只在非常奇怪的情况下才需要.

  • 通过"这只是在非常奇怪的情况下才需要"你指的是金钱是一种非常奇怪的情况吗? (4认同)
  • @Evan Plaice:钱不奇怪; 这是(通常)整数美分.如果您使用小数值来赚钱,那么您可能做错了. (4认同)
  • @Evan Plaice没有.为了钱,你使用整数.钱是*固定*精度:) (4认同)
  • @Greg,@ hobbs - Evan实际上100%正确.我猜你们两个都不在金融界工作?各种与金钱相关的事情都是分数 - 从应计利息到优惠券到外汇兑换的费用......你在银行对账单上看到的整齐美分是一个(im)礼貌小说 (4认同)