Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Integer overflow question

by martell (Hermit)
on Jan 02, 2005 at 17:05 UTC ( [id://418795]=perlquestion: print w/replies, xml ) Need Help??

martell has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

I like to program a transaction counter. To prevent integer overflow I added a little test on the maximum number the counter may have before it restarts.

My remaining question now: To keep the code portable: how can I retrieve the system's maximum representable integer in perl? Or do I have to make a 'save' assumption (not a very elegant solution)?

Any CPAN module available?

Thank you in advance.

Martell

Replies are listed 'Best First'.
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
      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)

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.

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


      -Waswas

      Someone looking at your example could think that use bigint alters how many digits print outputs, but that would be wrong. Here's a better example:

      { $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". }
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

      Similarly, you might check out POSIX, which provides an interface to various system constants.

      -xdg

      Code posted by xdg on PerlMonks is public domain. It has no warranties, express or implied. Posted code may not have been tested. Use at your own risk.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://418795]
Approved by tinita
Front-paged by grinder
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others lurking in the Monastery: (3)
As of 2024-04-25 20:59 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found