我怎样才能在Perl中使用大字符?

时间:2009-05-06 07:43:01

标签: perl printf bignum

在Windows 32位平台上,我必须阅读一些数字,这是意料之外的,可以有99,999,999,999这样的值,但不多了。试图sprintf("%011d", $myNum)输出溢出:-2147483648。

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

我该如何管理?打包/打包可以提供一些帮助吗?

5 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

是的,Perl的一个数字盲点是格式化; Perl自动将数字表示为整数或浮点数,但随后将它们强制转换为 使用printf数字格式时的一个或另一个,即使不是 适当。并且printf根本没有真正处理BigInts(除了通过处理 它们作为字符串并将其转换为数字,但精度不高。)

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

答案 2 :(得分:0)

我不是Perl专家,也许我在这里缺少某种自动处理bignums,但这不仅仅是整数溢出的情况吗? 32位整数不能保存大到99,999,999,999的数字。

无论如何,我在32位Linux机器上使用Perl v5.8.8得到了相同的结果,看起来带有“%d”的printf无法处理更大的数字。

答案 3 :(得分: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位上进行自己的测试,但是你可以使用你想要的任何缩放因子(如果需要,可以包括两个以上的段)。 / p>

更新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

答案 4 :(得分:0)

浮点数最多可以起作用。

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吗?) 可以打印吗?

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";