4

在 Windows 32 位平台上,我必须阅读一些数字,这是出乎意料的,它们的值可能高达 99,999,999,999,但仅此而已。尝试对sprintf("%011d", $myNum)它们输出溢出:-2147483648。

我不能使用 BigInt 模块,因为在这种情况下,我应该深入更改代码。我无法将格式管理为字符串, sprintf("%011s", $numero),因为减号处理不正确。

我该如何管理?打包/解包会有所帮助吗?

4

5 回答 5

11

尝试将其格式化为没有小数部分的浮点数:

$ perl -v
This is perl, v5.6.1 built for sun4-solaris
...

$ perl -e 'printf "%011d\n", 99999999999'
-0000000001

$ perl -e 'printf "%011.0f\n", 99999999999'
99999999999
于 2009-05-06T11:18:54.837 回答
1

是的,Perl 的数字盲点之一是格式化。Perl 会自动很好地处理将数字表示为整数或浮点数,但是当使用printf数字格式时,即使不合适,也会将它们强制转换为其中一种。并且printf根本不真正处理 BigInts(除非将它们视为字符串并将其转换为数字,但会丢失精度)。

使用 %s 而不是 %d 与您不确定是否在适当范围内的任何数字是一个很好的解决方法,除非您注意负数。要处理这些,您将不得不编写一些 Perl 代码。

于 2009-05-06T08:48:22.203 回答
1

在一定程度上,浮点数可以工作。

perl -e "printf qq{%.0f\n}, 999999999999999"
999999999999999

但仅在一定程度上

perl -e "printf qq{%.0f\n}, 9999999999999999999999999999999999999999999999"
9999999999999998663747590131240811450955988992

Bignum 在这里没有帮助。

perl -e "use bignum ; printf qq{%.0f\n}, 9999999999999999999999999999999999999999999999"
9999999999999999931398190359470212947659194368    

问题是printf。(你真的需要 printf 吗?) print 可以工作吗?

perl -e "use bignum;print 9999999999999999999999999999999999999999999999"
9999999999999999999999999999999999999999999999

说了这么多,关于 perl 的好处是它始终是您自己的选项。

例如

my $in = ...;
my $out = "";
while($in){
  my $chunk=$in & 0xf;
  $in >>= 4;
  $out = sprintf("%x",$chunk).$out;
}
print "0x$out\n";
于 2019-10-23T09:52:12.987 回答
0

我不是 Perl 专家,也许我在这里错过了某种对 bignums 的自动处理,但这不只是整数溢出的情况吗?32 位整数不能容纳 99,999,999,999 这样大的数字。

无论如何,我在我的 32 位 Linux 机器上使用 Perl v5.8.8 得到了相同的结果,而且带有 "%d" 的 printf 似乎不能处理更大的数字。

于 2009-05-06T07:51:15.460 回答
0

我认为您的 Perl 副本必须被破坏,这是来自 CygWin 的版本(5.10):

pax$ perl -e 'printf("%011d\n", 99999999999);'
99999999999

pax$ perl -v

This is perl, v5.10.0 built for cygwin-thread-multi-64int
(with 6 registered patches, see perl -V for more detail)

Copyright 1987-2007, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.

您正在运行什么版本(输出perl -v)?

您可能需要获得支持 64 位的 Perl 版本 [可能还有新的 64 位生产机器](请注意"cygwin-thread-multi-64int"我的输出中的 )。这至少可以避免更改代码的需要。

我是在您不想大幅更改代码的基础上说明这一点的(即,您害怕破坏事物)。新硬件的解决方案虽然有点贵,但几乎可以肯定根本不需要您更改软件。这取决于您的优先事项。

另一种可能性是 Perl 本身可能正确地存储了数字,但由于存在printf()缺陷而只是显示错误。在这种情况下,您可能想尝试:

$million = 1000000;
$bignum = 99999999999;
$firstbit = int($bignum / $million);
$secondbit = $bignum - $firstbit * million;
printf ("%d%06d\n",$firstbit,$secondbit);

把它放在一个函数中并调用该函数以返回一个字符串,例如:

sub big_honkin_number($) {
    $million = 1_000_000;
    $bignum = shift;
    $firstbit = int($bignum / $million);
    $secondbit = $bignum - $firstbit * $million;
    return sprintf("%d%06d\n", $firstbit, $secondbit);
}
printf ("%s", big_honkin_number (99_999_999_999));

请注意,我在 64 位平台上对此进行了测试——您需要在 32 位平台上进行自己的测试,但您可以使用您想要的任何缩放因子(如果需要,包括两个以上的段)。

更新:这个big_honkin_number()技巧在 32 位 Perl 上运行良好,所以看起来它只是让你感到厌烦的printf()函数:

pax@pax-desktop:~$ perl -v

This is perl, v5.8.8 built for i486-linux-gnu-thread-multi

Copyright 1987-2006, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.

pax@pax-desktop:~$ perl qq.pl
99999999999
于 2009-05-06T08:30:39.623 回答