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

时间:2022-09-06 16:28:09

On a Windows 32-bit platform I have to read some numbers that, this was unexpected, can have values as big as 99,999,999,999, but no more. Trying to sprintf("%011d", $myNum) them outputs an overflow: -2147483648.

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

I cannot use the BigInt module because in this case I should deeply change the code. I cannot manage the format as string, sprintf("%011s", $numero), because the minus sign is incorrectly handled.

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

How can I manage this? Could pack/unpack be of some help?

我该怎么办呢?打包/打包可以提供一些帮助吗?

4 个解决方案

#1


Try formatting it as a float with no fraction part:

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

$ 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

#2


Yes, one of Perl's numeric blind spots is formatting; Perl automatically handles representing numbers as integers or floats pretty well, but then coerces them into one or the other when the printf numeric formats are used, even when that isn't appropriate. And printf doesn't really handle BigInts at all (except by treating them as strings and converting that to a number, with loss of precision).

是的,Perl的一个数字盲点是格式化; Perl自动将数字表示为整数或浮点数,但是当使用printf数字格式时,它们会将它们强制转换为一个或另一个,即使这是不合适的。并且printf根本不会真正处理BigInts(除非将它们视为字符串并将其转换为数字,但精度会降低)。

Using %s instead of %d with any number you aren't sure will be in an appropriate range is a good workaround, except as you note for negative numbers. To handle those, you are going to have to write some Perl code.

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

#3


I'm no Perl expert, and maybe I'm missing some sort of automatic handling of bignums here, but isn't this simply a case of integer overflow? A 32-bit integer can't hold numbers that are as big as 99,999,999,999.

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

Anyway, I get the same result with Perl v5.8.8 on my 32-bit Linux machine, and it seems that printf with "%d" doesn't handle larger numbers.

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

#4


I think your copy of Perl must be broken, this is from CygWin's version (5.10):

我认为你的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.

What version are you running (output of perl -v)?

你在运行什么版本(perl -v的输出)?

You may have to get a 64-bit enabled version of Perl [and possibly a new 64-bit production machine] (note the "cygwin-thread-multi-64int" in my output). That will at least avoid the need for changing the code.

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

I'm stating this on the basis that you don't want to change the code greatly (i.e., you fear breaking things). The solution of new hardware, whilst a little expensive, will almost certainly not require you to change the software at all. It depends on your priorities.

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

Another possibility is that Perl itself may be storing the number correctly but just displaying it wrong due to a printf() foible. In that case, you may want to try:

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

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

Put that in a function and call the function to return a string, such as:

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

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

Note that I tested this but on the 64-bit platform - you'll need to do your own test on 32-bit but you can use whatever scaling factor you want (including more than two segments if need be).

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

Update: That big_honkin_number() trick works fine on a 32-bit Perl so it looks like it is just the printf() functions that are stuffing you up:

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

#1


Try formatting it as a float with no fraction part:

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

$ 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

#2


Yes, one of Perl's numeric blind spots is formatting; Perl automatically handles representing numbers as integers or floats pretty well, but then coerces them into one or the other when the printf numeric formats are used, even when that isn't appropriate. And printf doesn't really handle BigInts at all (except by treating them as strings and converting that to a number, with loss of precision).

是的,Perl的一个数字盲点是格式化; Perl自动将数字表示为整数或浮点数,但是当使用printf数字格式时,它们会将它们强制转换为一个或另一个,即使这是不合适的。并且printf根本不会真正处理BigInts(除非将它们视为字符串并将其转换为数字,但精度会降低)。

Using %s instead of %d with any number you aren't sure will be in an appropriate range is a good workaround, except as you note for negative numbers. To handle those, you are going to have to write some Perl code.

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

#3


I'm no Perl expert, and maybe I'm missing some sort of automatic handling of bignums here, but isn't this simply a case of integer overflow? A 32-bit integer can't hold numbers that are as big as 99,999,999,999.

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

Anyway, I get the same result with Perl v5.8.8 on my 32-bit Linux machine, and it seems that printf with "%d" doesn't handle larger numbers.

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

#4


I think your copy of Perl must be broken, this is from CygWin's version (5.10):

我认为你的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.

What version are you running (output of perl -v)?

你在运行什么版本(perl -v的输出)?

You may have to get a 64-bit enabled version of Perl [and possibly a new 64-bit production machine] (note the "cygwin-thread-multi-64int" in my output). That will at least avoid the need for changing the code.

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

I'm stating this on the basis that you don't want to change the code greatly (i.e., you fear breaking things). The solution of new hardware, whilst a little expensive, will almost certainly not require you to change the software at all. It depends on your priorities.

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

Another possibility is that Perl itself may be storing the number correctly but just displaying it wrong due to a printf() foible. In that case, you may want to try:

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

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

Put that in a function and call the function to return a string, such as:

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

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

Note that I tested this but on the 64-bit platform - you'll need to do your own test on 32-bit but you can use whatever scaling factor you want (including more than two segments if need be).

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

Update: That big_honkin_number() trick works fine on a 32-bit Perl so it looks like it is just the printf() functions that are stuffing you up:

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