Perl / perl5

🐪 The Perl programming language
https://dev.perl.org/perl5/
Other
1.94k stars 554 forks source link

"use integer" behaving oddly for large unsigned values #14515

Closed p5pRT closed 9 years ago

p5pRT commented 9 years ago

Migrated from rt.perl.org#123851 (status was 'rejected')

Searchable as RT123851$

p5pRT commented 9 years ago

From @sisyphus

Hi\,

On all recent perls that I've tried \,including blead\, 5.18.0 and 5.20.0\, on linux and windows I'm getting stuff such as​:

$ perl -Minteger -le '$x = 10_000_000_000_000_000_011; print $x; print $x / 10;' 10000000000000000011 -844674407370955160

The actual perl configuration doesn't seem to matter except that ivsize has to be 8\, and the numerator is larger than 2 ** 63.

Similarly\, if ivsize is 4\, and the numerator is greater than 2 ** 31 I get such outputs as​:

C​:\>perl -Minteger -le "$x = 3147483661; print $x; print $x / 10;" 3147483661 -114748363

I can't see anything in the integer documentation that explains this. The only reference I see there in relation to signed/unsigned issues pertains to the bitwise operators.

Cheers\, Rob

p5pRT commented 9 years ago

From @hvds

On Mon Feb 16 19​:11​:30 2015\, sisyphus wrote​:

I can't see anything in the integer documentation that explains this. The only reference I see there in relation to signed/unsigned issues pertains to the bitwise operators.

I think the relevant bit is this part in the second para of the description​:

  [...] In addition\, the range of operands and results is   restricted to that of familiar two's complement integers\, i.e.\,   -(2**31) .. (2**31-1) on 32-bit architectures\, and -(2**63) ..   (2**63-1) on 64-bit architectures. [...]

I believe an initially assigned constant is treated as a float (by parts of perl that the integer module can't reach) until you use it numerically. So here's where it first wraps to negative for 64-bit ints​:

% perl -wle 'for (9223372036854775807\, 9223372036854775808) { my $x = $_; printf "%s = %#x\n"\, $x\, $x; use integer; print $x; $x += 0; print $x }' 9223372036854775807 = 0x7fffffffffffffff 9223372036854775807 9223372036854775807 9223372036854775808 = 0x8000000000000000 9223372036854775808 -9223372036854775808 %

Hugo

p5pRT commented 9 years ago

The RT System itself - Status changed from 'new' to 'open'

p5pRT commented 9 years ago

From @ikegami

bigint says " Integer constants are created as proper BigInts." To me\, that means the following two snippets should be equivalent​:

$ perl -Minteger -le '$x = 10_000_000_000_000_000_011; print $x; print $x / 10;' 10000000000000000011 -844674407370955160

$ perl -MMath​::BigInt -le '$x = Math​::BigInt->new("10_000_000_000_000_000_011"); print $x; print $x / Math​::BigInt->new("10");' 10000000000000000011 1000000000000000001

So I agree with Sisyphus. Something isn't right.

p5pRT commented 9 years ago

From @hvds

On Mon Feb 16 20​:48​:24 2015\, ikegami@​adaelis.com wrote​:

bigint says [snip] $ perl -Minteger [snip]

I'm confused​: 'bigint' ne 'integer'\, so I'm not sure of the relevance of this comment. The 'integer' module has nothing to do with bigints.

Hugo

p5pRT commented 9 years ago

From @tonycoz

On Mon Feb 16 20​:48​:24 2015\, ikegami@​adaelis.com wrote​:

bigint says " Integer constants are created as proper BigInts." To me\, that means the following two snippets should be equivalent​:

$ perl -Minteger -le '$x = 10_000_000_000_000_000_011; print $x; print $x / 10;' 10000000000000000011 -844674407370955160

$ perl -MMath​::BigInt -le '$x = Math​::BigInt->new("10_000_000_000_000_000_011"); print $x; print $x / Math​::BigInt->new("10");' 10000000000000000011 1000000000000000001

So I agree with Sisyphus. Something isn't right.

bigint has a bigger range than the documented range of "-(2**63) .. (2**63-1) on 64-bit architectures".

There are examples in perldoc integer documenting the wrapping behaviour.

What behaviour do you expect given the documentation?

Tony

p5pRT commented 9 years ago

From @sisyphus

-----Original Message----- From​: Tony Cook via RT Sent​: Tuesday\, February 17\, 2015 4​:35 PM

$ perl -Minteger -le '$x = 10_000_000_000_000_000_011; print $x; print $x / 10;' 10000000000000000011 -844674407370955160

$ perl -MMath​::BigInt -le '$x = Math​::BigInt->new("10_000_000_000_000_000_011"); print $x; print $x / Math​::BigInt->new("10");' 10000000000000000011 1000000000000000001

There are examples in perldoc integer documenting the wrapping behaviour.

What behaviour do you expect given the documentation?

I think I expected such a significant and crippling limitation to be spelled out in a more glaringly obvious way. But you're right - if you read the documentation properly it's all there.

So ... if you're wanting to do integer arithmetic on perl UV's that might be large enough to break the fragility of the integer pragma\, then Math​::BigInt is the only readily available option without venturing outside core perl. Is that right ?

Anyway - feel free to close this report. (I won't be using the integer pragma while it's in this state.) Sorry for the noise.

Cheers\, Rob

p5pRT commented 9 years ago

From @tonycoz

On Tue Feb 17 01​:35​:44 2015\, sisyphus wrote​:

Anyway - feel free to close this report. (I won't be using the integer pragma while it's in this state.) Sorry for the noise.

Ok\, closing.

Tony

p5pRT commented 9 years ago

@tonycoz - Status changed from 'open' to 'rejected'

p5pRT commented 9 years ago

From @ikegami

On Tue\, Feb 17\, 2015 at 12​:18 AM\, Hugo van der Sanden via RT \< perlbug-followup@​perl.org> wrote​:

On Mon Feb 16 20​:48​:24 2015\, ikegami@​adaelis.com wrote​:

bigint says [snip] $ perl -Minteger [snip]

I'm confused​: 'bigint' ne 'integer'\, so I'm not sure of the relevance of this comment. The 'integer' module has nothing to do with bigints.

No\, I'm the confused one. Ignore my message.