这个Perl格式化错误的原因是什么?

时间:2010-11-12 16:47:37

标签: perl

$str =sprintf "%014ld", "2555600000";
print $str;

这给了我结果:

-0001739367296

负数。这种行为有原因吗?

3 个答案:

答案 0 :(得分:11)

2555600000太大,无法容纳32位有符号整数。 转换为二进制,它是10011000 01010011 01011100 10000000,当解释为带符号的32位整数时代表-0001739367296

您的选择是:

my $str = sprintf("%014u", 2555600000);     # unsigned integer
my $str = sprintf("%014.0f", 2555600000);   # floating point
my $str = sprintf("%014s", 2555600000);     # string

第一个适用于此数字,但不是更高的数字。对于非常高的数字,第二个可能变得不准确。 (但是对于标准浮点“双”,您应该很容易准确地使用您正在使用的14位数。第三个可能是最简单的,只需将其视为字符串并忘记它是一个数字。

要查看您的版本使用了多少位,您可以运行perl -V。示例输出:

...
intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
...

所以我的Perl使用4字节,32位整数。

答案 1 :(得分:5)

$ perl -e '$str =sprintf "%014ld", "2555600000"; print $str, "\n";'
00002555600000

它对我有用。但是,您给出的数字大于32位有符号整数可以容纳的数字,那么您的结果可能意味着您使用的是32位机器?

答案 2 :(得分:4)

不幸的是,printf修饰符与底层C类型相当紧密耦合(尽管大小由perl -ld确定,与d没有区别,但在下面,perl将使用它为其构建的int的限定符大小)。 p>

所以%d会将一个数字转换为有符号的int,将%u转换为unsigned int,即使perl知道它实际上是什么。

你通常最好只使用%s:

$ perl -wle'printf "%014s\n%014d\n", "2555600000", "2555600000";'
00002555600000
-0001739367296