Re: Integer overflow question
by thospel (Hermit) on Jan 02, 2005 at 19:02 UTC
|
The answer to this sort of question is not that straightforward. If you use a 32-bit perl, your values start out as an IV (integer value), so you might think the maximum is 2**31-1. If you however add one to that, the value will become an UV (unsigned integer value), and you might think the maxiumum is 2**32-1. However, when you add 1 to that, the value becomes a NV (float value). That one has a very high
maximum value, but that one is in fact irrelevant because long before that point you lose resolution and adding 1 will not change the value anymore. That typically happens somewhere around 9e15 (depends on the exact float resolution on your system). Still, this should be way beyond any foreseeable number of transactions unless you do millions of them per second (though if you need a string representation you may have to use (s)printf in order to get all significant digits).
Conclusion: normally you simply don't have to worry about integer overflow of a counter at the perl end.
If you need even more digits (or don't want to bother with (s)printf for big values), simply use an integer in string form and use ++, which will then be magic and have
no restriction whatsoever, e.g.:
perl -wle '$a = "9" x 100; $a++; print $a'
will give you 1 folowed by 100 zeros | [reply] [d/l] |
|
That typically happens somewhere around 9e15
The resolution typically is 53 bits, as customary in IEEE floats.
print 2**53;
__END__
9.00719925474099e+015
and on my system:
$\ = "\n";
my $x = 2**53;
my $y = 2**53+1;
my $z = 2**53-1;
print $y-$x;
print $x-$z;
__END__
0
1
So that is indeed the threshold here. (ActivePerl 5.8.4 on Win32) | [reply] [d/l] [select] |
Re: Integer overflow question
by ambrus (Abbot) on Jan 02, 2005 at 17:43 UTC
|
The largest representable unsigned integer is ~0,
the largest signed integer is (~0-1)/2.
If you use floating point numbers
(too large integers get converted to floating point numbers automatically),
however, you have a higher upper limit.
If $f = 1; $f *= 2 until $f * 2 == $f * 2 - 1;
than you can increment the counter up to $f,
but no more.
$f is 9007199254740992 on my machine.
However, you have to print these with
printf "%.0f", not simple print,
or you'll lose precision when printing.
| [reply] [d/l] [select] |
Re: Integer overflow question
by holli (Abbot) on Jan 02, 2005 at 19:37 UTC
|
if you use bigint; you will have never have to worry.
#bad
print 2**59, "\n"; #5.76460752303423e+017
print 2**59+1, "\n"; #5.76460752303423e+017
#good
use bigint;
print 2**59, "\n"; #576460752303423488
print 2**59+1, "\n"; #576460752303423489
| [reply] [d/l] [select] |
|
Another thing you may want to mention about bigint is that it is slower than incrementing a normal int. This may be a limiting factor in a counter that is used in a very tight loop (requirement that it support very large ints could mean tight loop or long run).
| [reply] |
|
{
$a = 2**59; # Saved as a limited precision float.
$b = 2**59 + 1; # Saved as a limited precision float.
print($a, $/); # Prints "5.76460752303423e+017".
print($b, $/); # Prints "5.76460752303423e+017".
print($b-$a, $/); # Prints "0".
}
{
use bigint;
$a = 2**59; # Saved as an unlimited precision int.
$b = 2**59 + 1; # Saved as an unlimited precision int.
print($a, $/); # Prints "576460752303423488".
print($b, $/); # Prints "576460752303423489".
print($b-$a, $/); # Prints "1".
}
| [reply] [d/l] [select] |
Re: Integer overflow question
by Courage (Parson) on Jan 02, 2005 at 17:17 UTC
|
may be you need following: use Config;
print $Config{intsize};
?
In this case do perldoc Config
Best regards,
Courage, the Cowardly Dog
| [reply] [d/l] [select] |
|
| [reply] |