1

谁能解释一下这是怎么回事:

#!/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 条目:如何消除 Perl 舍入错误,但老实说,我没想到会看到这样一个看似简单的示例出现问题。

$amount 的值也是正确的。只是 printf 没有正确打印!

有任何想法吗?

4

1 回答 1

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
于 2014-02-12T10:30:58.780 回答