Google 网上论坛不再支持新的 Usenet 帖子或订阅项。历史内容仍可供查看。

Strange behavior when printing a 4G+ integer on 32bits platform.

已查看 4 次
跳至第一个未读帖子

Tetsuo Handa

未读,
2018年11月13日 09:15:042018/11/13
收件人 begi...@perl.org
Hello.

I want to represent up to a few hundreds gigabytes for file size.

On 32bits platform, I noticed that

my $value = ...;
printf("%u\n", $value);

prints 4294967295 if $value >= 4294967295 whereas

my $value = ...;
printf("%s\n", $value);

and

use Math::BigInt;
my $value = ...;
printf("%s\n", Math::BigInt->new($value)->bstr());

print correct value even when $value >= 4294967295.

Is it guaranteed (e.g. described as language specification) that
printf("%s\n", $value) will print correct value for any environment?

Mike Flannigan

未读,
2018年11月13日 10:15:042018/11/13
收件人 begi...@perl.org、penguin...@i-love.sakura.ne.jp

I don't have an answer for you, but I find this
interesting.  I note the same issue in 64bit
up near
18446744073709551615

I'm guessing the guy who wrote
Math::BigInt
may have the answer.


Mike

Tetsuo Handa

未读,
2018年11月15日 17:00:052018/11/15
收件人 Mike Flannigan、begi...@perl.org
I received a comment from Peter John Acklam (current bigint maintainer).

-------- Forwarded Message --------
Date: Wed, 14 Nov 2018 20:08:27 +0100

Hello

This has actually nothing to do with Math::BigInt. The issue here is that
the conversion "u", converts a number to an unsigned integer before the
integer is printed as a string. On 32 bit systems, an unsigned integer has
values between 0 and 2^32-1, inclusive. On 64 bit systems, the values are
between 0 and 2^64-1. Using input values outside of this range is not a
good idea. It seems that if the input is larger than the maximum value, it
is truncated to the maximum value, but I wouldn't rely on this. On my 64
bit system, the input value is truncated:

$ perl -we 'printf "%u\n", "1e30"'
18446744073709551615

On the other hand, when the input value is smaller than zero, the input is
not truncated to zero on my system:

$ perl -we 'printf "%u\n", "-1e30"'
9223372036854775808

As for the "s" conversion, it never converts the input to an integer (or
float). Strings are passed right through, unmodified. So that's why I get

$ perl -we 'printf "%s\n", "1e30"'
1e30

If you want "1e30" to be displayed as "100...", Math::BigInt is handy for
converting "1e30" to "100...":

$ perl -MMath::BigInt -we 'printf "%s\n", Math::BigInt->new("1e30")->bstr()'
1000000000000000000000000000000

Regarding the question "Is it guaranteed (e.g. described as language
specification) that printf("%s\n", $value) will print correct value
for any environment?"
Yes, the "s" conversion passes strings through unmodified.

If you have more questions or want more clarification, don't hesitate to
ask again.

Best regards,
Peter

Tetsuo Handa

未读,
2018年11月17日 18:30:042018/11/17
收件人 begi...@perl.org

Tetsuo Handa

未读,
2018年11月17日 18:45:032018/11/17
收件人 begi...@perl.org
0 个新帖子