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.
| [reply] [d/l] [select] |
Re: How to portably determine integer limits?
by BrowserUk (Patriarch) 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!
| [reply] [d/l] |
|
| [reply] [d/l] [select] |
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. |
| [reply] |
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 | [reply] |
|
>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 | [reply] [d/l] |
|
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
| [reply] [d/l] |
|
|
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.
| [reply] [d/l] |
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.
| [reply] |
|
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. :) | [reply] [d/l] [select] |
|
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..
| [reply] |
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! | [reply] |