任何人都可以解释这个:
#!/usr/bin/perl -w
my $amount = 74.32 * 100.00;
printf "Unformatted Amount:${amount}:\n";
printf " Formatted Amount:%.11d:\n", $amount;
输出:
$ ./test.pl
Unformatted Amount:7432:
Formatted Amount:00000007431:
目前我已停止使用printf和sprintf,因为我不相信它们。所以我这样做了:
#!/usr/bin/perl -w
my $amount = 74.32 * 100.00;
$formatted_amount = "00000000000" . $amount;
$formatted_amount = substr($formated_amount,length($formatted_amount)-11,11);
printf "Unformatted Amount:${amount}:\n";
printf " Formatted Amount:${formatted_amount}:\n";
虽然有效但我很想知道为什么我需要这样做。
我理解二进制数字如何不能完全代表所有基数为10的数字,并且已经阅读了这个Stack Overflow条目:How to eliminate Perl rounding errors,但老实说我没想到看到这个看似简单的例子有问题。
$ amount 的值也是正确的。这只是printf无法正确打印!
有什么想法吗?
答案 0 :(得分:4)
我认为printf
应该放弃你!
您希望%.11d
的说明符做什么?
小数点后的值是精度,而perldoc -f sprintf
表示
对于整数转换,指定精度意味着 数字本身的输出应为零填充 这个宽度,忽略0标志
如果你想要一个11个字符的最小宽度而不是省略小数点 - %11d
会给你你想要的。
Perl通过截断将浮点数转换为整数,并且74.32 * 100.0
略小于而不是7432,int(74.32 * 100.0)
为7431。您希望浮点值四舍五入到最接近的整数,然后使用f
格式说明符,其精度为零,如%11.0f
。
要填充字段,请查看上述文档的标记部分。标志字符出现在宽度说明符之前:0 use zeros, not spaces, to right-justify
。
检查此程序
use strict;
use warnings;
my $amount = 74.32 * 100.00;
printf "Unformatted Amount: ${amount}\n";
printf "Truncated Amount: %d\n", $amount;
printf "High-precision Amount: %20.16f\n", $amount;
printf "Rounded Amount: %.0f\n", $amount;
printf "Padded Amount: %011.0f\n", $amount;
<强>输出强>
Unformatted Amount: 7432
Truncated Amount: 7431
High-precision Amount: 7431.9999999999991000
Formatted Amount: 7432
Padded Amount: 00000007432