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

How to portably determine integer limits?

by Anonymous Monk
on Oct 29, 2003 at 23:30 UTC ( #303146=perlquestion: print w/replies, xml ) Need Help??

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

Is there an elegant way to determine the maximum and minimum integer limits? perlnumber says:
  "Thus the limits for Perl numbers stored as native integers would
    typically be -2**31..2**32-1"
It's that "typically" bit that suggests I need to determine the limits myself!

I could ++/-- an integer scalar until I hit the limit, but that seems pretty naff.

I'm also guessing POSIX may have the limits defined, but I'd prefer not to use POSIX if possible.

Any suggestions?

  • Comment on How to portably determine integer limits?

Replies are listed 'Best First'.
Re: How to portably determine integer limits?
by jmcnamara (Monsignor) on Oct 29, 2003 at 23:41 UTC

    One way is to use the core Config module and calculate the limits from the byte size:
    #!/usr/bin/perl -wl use Config; print $Config{intsize};
    Another way, as you guessed, is with POSIX:
    use POSIX; print POSIX::INT_MAX; print POSIX::INT_MIN; print POSIX::UINT_MAX;

    Or perhaps even this:

    print 0.5 * (-1 + unpack "I", pack "I", -1); print 0.5 * (-1 - unpack "I", pack "I", -1); print unpack "I", pack "I", -1 ;

    --
    John.

Re: How to portably determine integer limits?
by BrowserUk (Pope) on Oct 30, 2003 at 00:13 UTC
    # Largest unsigned integer. print ~0; # The largest signed integer print +(~0)>>1; # Smallest signed integer. $n = (~0)>>1; print do{ use integer; ~$n };

    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
    Hooray!

      Somewhat simpler versions of the last two are ~0>>1 and -(~0>>1)-1.

                      - tye
Re: How to portably determine integer limits?
by PodMaster (Abbot) on Oct 29, 2003 at 23:41 UTC
    perldoc Config
    perldoc perlrun
    perl -V:intsize
    perl -MConfig -e"die $Config{intsize}"
    perl -MConfig -e'die $Config{intsize}'
    perl -V:.+ |perl -ne"print if /int/"
    perl -V:.+ |perl -ne'print if /int/'
    

    MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
    I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
    ** The third rule of perl club is a statement of fact: pod is sexy.

Re: How to portably determine integer limits?
by Abigail-II (Bishop) on Oct 30, 2003 at 00:15 UTC
    The question is, which integer limits do you mean? The suggested POSIX INT_MAX and INT_MIN, and $Config {intsize} gives information about the native integers of your system. But that's not necessarely the same as the integer range of your Perl! If you build your Perl to have 64 bit integers POSIX::INT_MAX might still be 2147483647 and $Config {intsize} be 4. But then Perl is using longlongs as integers, and you should be looking at $Config {longlongsize}.

    Abigail

      >The question is, which integer limits do you mean?

      Ok - I mean the min/max integer value for a scalar $i at the point where $i-- or $i++ will overflow and fail to return the expected value.

      I want to minimise the use of Math::BigInt where possible, so I'm looking to do something like:

      $integer_upper_limit = Math::BigInt->new($whatever_the_upper_limit_i +s); $number = get_integer_number_string_from_somewhere(); $number = Math::BigInt->new($number) if $integer_upper_limit->bcmp($ +number) < 0;
      Ditto for negative.

      Hope that make better sense!

      Edit by tye, change PRE to CODE around not-short lines

        Ok - I mean the min/max integer value for a scalar $i at the point where $i-- or $i++ will overflow and fail to return the expected value.
        Ah, that's yet another question. First of all, Perl numbers don't "overflow" in the sense that adding 1 to a really big positive number gives you are really small negative number.

        Say you have:

        $i = 0; $i ++ while forever;
        What happens is:
        • $i starts life as a value where its value is represented as an integer.
        • At one moment, the integer has insufficient bits to represent $i. Then perl starts using a floating point number, typically a double.
        • Due to rounding it won't happen if you keep adding 1, but if you keep increasing $i, even the floating point number will run out of bits; then $i becomes "not a number".
        If your double has more bits than your integer (a very typical situation, specially in older perls, is having 32 bit integers and 64 bit doubles), there's an interesting situation after the change of representation. 64 bit doubles still have something like 53 bits of precision. So, even with 32 integers, you can still store numbers needing 53 bits without losing precision. And I guess something similar will happen if you have 64 bit integers, and 128 bit doubles.

        Abigail

        I didn't see any good answers to this given. I'd do:

        my $x= 1+~0; $x *= 2 while $x != $x+1; print "You can safely use integer values between ", -$x/2, " and ", $x/2, $/; # -$x, " and ", $x-1, $/;
        where you could choose to use that last line instead of the second-to-last line if you aren't paranoid like me.

                        - tye
Re: How to portably determine integer limits?
by pg (Canon) on Oct 30, 2003 at 02:12 UTC

    The question itself is actually questionable. As Perl is not a language with strong type, the upper or lower limits of integer themselves, do not really put much restriction on the things one "typically" (another typically ;-) does.

    Again because Perl is not a strong type language, the plan to use ++/-- ONLY to hit the integer limits are not doable, unless you sneak some other stuffs in.

    Integer limits produce much less worries in Perl, than they do in other languages. At least the worry is from a totally different sense.

      There are reasons to worry, most notable with regards to the bitwise operands, &, |, ^, ~ on one hand, << and >> on the other. And % also has a limit on the range for which it works reliable — very system dependent, I've had a perl 5.005 for which modulo calculations with a number > 2**32 always returned zero, but on my newer port, I can go up to 2**52 or 2**53 (I don't recall exactly), the mantissa part of an IEEE double float, of 64 bits.

      This meaningfulness does give a clue on how to efficiently test how large the range can be: I'm quite convinced the limit is always closely related to a power of 2 so one could shift a number to the left, until the result differs from the number times 2, in floating point calculation.

      my $i = 0; my $n = my $m = 1; while($n == $m) { $n <<= 1; $m *= 2; $i++; } print "different for $m (2**$i)\n";
      I get:
      different for 4294967296 (2**32)
      
      What precisely this implies, I leave as an exercise for the reader. :)
        Just in case you were not writing out your thoughts so the reader can learn...

        The limits are of a power of 2.. 'cause it's binary. For every extra bit you tack on, you are adding to a position representing 2^(N+1) position, after the most significant bit. Adding to a 1 bit number makes it 2 bits and a max of 3 (4-1). Adding another bit makes it a 3 bit number, and givig it a max of 7 (8-1), It's minus one just 'cause that's how binary works. 2^n would be 1000....

        Same w/ char's (2^8 in ascii), unicode, (2^8 * 2 == 2^16)..

        With signed numbers, it's a bit different.. since your most significant bit, teh bit with teh largest 2^n position would be, is just a bit saying if the number is negative or not. But for more reference on how that works, look up 2's compliment on google. :) I 'm going to bed.

        Play that funky music white boy..
Re: How to portably determine integer limits?
by Anonymous Monk on Oct 30, 2003 at 14:18 UTC
    Ok, confession time...

    Why was I getting overflows? If I'd noticed the "use integer" plonked in the module a bit earlier I wouldn't have posted this. No excuses though, since it must have been me who put it there in the first place :(

    At least I now understand how perl handles integer scalars, but nevertheless, sorry for the bogus posting dudes!

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (5)
As of 2020-11-26 02:09 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?