Maximum value for long integer - python

How can I assign the maximum value for a long integer to a variable, similar, for example, to C++'s LONG_MAX.

Long integers:
There is no explicitly defined limit. The amount of available address space forms a practical limit.
(Taken from this site). See the docs on Numeric Types where you'll see that Long integers have unlimited precision. In Python 2, Integers will automatically switch to longs when they grow beyond their limit:
>>> import sys
>>> type(sys.maxsize)
<type 'int'>
>>> type(sys.maxsize+1)
<type 'long'>
for integers we have
maxint and maxsize:
The maximum value of an int can be found in Python 2.x with sys.maxint. It was removed in Python 3, but sys.maxsize can often be used instead. From the changelog:
The sys.maxint constant was removed, since there is no longer a limit
to the value of integers. However, sys.maxsize can be used as an
integer larger than any practical list or string index. It conforms to
the implementation’s “natural” integer size and is typically the same
as sys.maxint in previous releases on the same platform (assuming the
same build options).
and, for anyone interested in the difference (Python 2.x):
sys.maxint The largest positive integer supported by Python’s regular
integer type. This is at least 2**31-1. The largest negative integer
is -maxint-1 — the asymmetry results from the use of 2’s complement
binary arithmetic.
sys.maxsize The largest positive integer supported by the platform’s
Py_ssize_t type, and thus the maximum size lists, strings, dicts, and
many other containers can have.
and for completeness, here's the Python 3 version:
sys.maxsize
An integer giving the maximum value a variable of type Py_ssize_t can take. It’s usually 2^31 - 1 on a 32-bit platform and
2^63 - 1 on a 64-bit platform.
floats:
There's float("inf") and float("-inf"). These can be compared to other numeric types:
>>> import sys
>>> float("inf") > sys.maxsize
True

Python long can be arbitrarily large. If you need a value that's greater than any other value, you can use float('inf'), since Python has no trouble comparing numeric values of different types. Similarly, for a value lesser than any other value, you can use float('-inf').

Direct answer to title question:
Integers are unlimited in size and have no maximum value in Python.
Answer which addresses stated underlying use case:
According to your comment of what you're trying to do, you are currently thinking something along the lines of
minval = MAXINT;
for (i = 1; i < num_elems; i++)
if a[i] < a[i-1]
minval = a[i];
That's not how to think in Python. A better translation to Python (but still not the best) would be
minval = a[0] # Just use the first value
for i in range(1, len(a)):
minval = min(a[i], a[i - 1])
Note that the above doesn't use MAXINT at all. That part of the solution applies to any programming language: You don't need to know the highest possible value just to find the smallest value in a collection.
But anyway, what you really do in Python is just
minval = min(a)
That is, you don't write a loop at all. The built-in min() function gets the minimum of the whole collection.

long type in Python 2.x uses arbitrary precision arithmetic and has no such thing as maximum possible value. It is limited by the available memory. Python 3.x has no special type for values that cannot be represented by the native machine integer — everything is int and conversion is handled behind the scenes.

Unlike C/C++ Long in Python have unlimited precision. Refer the section Numeric Types in python for more information.To determine the max value of integer you can just refer sys.maxint. You can get more details from the documentation of sys.

You can use: max value of float is
float('inf')
for negative
float('-inf')

A) For a cheap comparison / arithmetics dummy use math.inf. Or math.nan, which compares FALSE in any direction (including nan == nan) except identity check (is) and renders any arithmetics (like nan - nan) nan. Or a reasonably high real integer number according to your use case (e.g. sys.maxsize). For a bitmask dummy (e.g. in mybits & bitmask) use -1.
B) To get the platform primitive maximum signed long int (or long long):
>>> 256 ** sys.int_info.sizeof_digit // 2 - 1 # Python’s internal primitive
2147483647
>>> 256 ** ctypes.sizeof(ctypes.c_long) // 2 - 1 # CPython
2147483647
>>> 256 ** ctypes.sizeof(ctypes.c_longlong) // 2 - 1 # CPython
9223372036854775807
>>> 2**63 - 1 # Java / JPython primitive long
9223372036854775807
C) The maximum Python integer could be estimated by a long running loop teasing for a memory overflow (try 256**int(8e9) - can be stopped by KeyboardInterrupt). But it cannot not be used reasonably, because its representation already consumes all the memory and its much greater than sys.float_info.max.

Related

How can I make all Python3 numbers ctypes.c_int32?

I am trying to replicate C program behaviours using Python3 and repeatedly casting all numbers to ctypes.c_int32 get ugly real fast.
Is there any way I could default Python's int to be an instance of ctypes.c_int32?
Edit:
I would like to perform arithmetic operations between multiple c_int32 objects (e.g. xor-ing and and-ing), but I can't do this without adding .value behind every c_type int object. I want to see if I can somehow override the default python int object to behave more similarly to c_int32 in ctypes.
You can't do what you want in Python 3. int in Python 2.3 and earlier (before int/long integration) worked they way I think you want.
If you just want to constrain math results to signed int32 results ctypes isn't needed. The following truncates n to the lower 32 bits, then adjusts for the sign bit:
>>> def int32(n):
... n &= (1<<32)-1
... return n - (1<<32) if n & (1<<31) else n
...
>>> int32(-1)
-1
>>> int32(0x80000000) # sign bit set (bit 31)
-2147483648
>>> int32(0x7fffffff) # max positive int32
2147483647
>>> int32(0x7fffffff + 1) # overflow to sign bit
-2147483648
>>> 1<<31 # without constraint
2147483648
>>> int32(1<<31)
-2147483648
>>> 1<<32 # without constraint
4294967296
>>> int32(1<<32)
0

how python 3 handles big integers internally [duplicate]

In C, C++, and Java, an integer has a certain range. One thing I realized in Python is that I can calculate really large integers such as pow(2, 100). The same equivalent code, in C, pow(2, 100) would clearly cause an overflow since in 32-bit architecture, the unsigned integer type ranges from 0 to 2^32-1. How is it possible for Python to calculate these large numbers?
Basically, big numbers in Python are stored in arrays of 'digits'. That's quoted, right, because each 'digit' could actually be quite a big number on its own. )
You can check the details of implementation in longintrepr.h and longobject.c:
There are two different sets of parameters: one set for 30-bit digits,
stored in an unsigned 32-bit integer type, and one set for 15-bit
digits with each digit stored in an unsigned short. The value of
PYLONG_BITS_IN_DIGIT, defined either at configure time or in pyport.h,
is used to decide which digit size to use.
/* Long integer representation.
The absolute value of a number is equal to
SUM(for i=0 through abs(ob_size)-1) ob_digit[i] * 2**(SHIFT*i)
Negative numbers are represented with ob_size < 0;
zero is represented by ob_size == 0.
In a normalized number, ob_digit[abs(ob_size)-1] (the most significant
digit) is never zero. Also, in all cases, for all valid i,
0 <= ob_digit[i] <= MASK.
The allocation function takes care of allocating extra memory
so that ob_digit[0] ... ob_digit[abs(ob_size)-1] are actually available.
*/
struct _longobject {
PyObject_VAR_HEAD
digit ob_digit[1];
};
How is it possible for Python to calculate these large numbers?
How is it possible for you to calculate these large numbers if you only have the 10 digits 0-9? Well, you use more than one digit!
Bignum arithmetic works the same way, except the individual "digits" are not 0-9 but 0-4294967296 or 0-18446744073709551616.

Sum of consecutive integers in numpy is incorrect

In summing the first 100,000,000 positive integers using the following:
import numpy as np
np.arange(1,100000001).sum()
I return: 987459712, which does not match the formula: N(N+1)/2 for N=100000000. Namely, the formula returns 5000000050000000.
Before posting, I wrote the following, which returns True:
np.arange(1,65536).sum() == ((65535+1) * 65535)/2
However, the number 65536 seems to be a critical point, as
np.arange(1,65537).sum() == ((65536+1) * 65536)/2
returns False.
For integers greater than 65536 the code returns False, whereas integers below this threshold return True.
Could someone explain either what I've done wrong in calculating the sum, or what is going on with the code?
Seems like numpy sometimes has a hard time guessing the correct datatype.
On my system, Win 10 64-bit, Python 3.4.4, numpy 1.13.1:
>> np.arange(1, 100000001).sum()
987459712
>> np.arange(1, 100000001).dtype
dtype('int32')
But, if we "help" numpy it gets the correct result:
>> np.arange(1, 100000001, dtype=np.int64).sum()
500000005000000
The wrong result is obviously due to 32-bit integer overflowing.
It isn't really that numpy has a hard time guessing things, it's just that the default int type is the same as C long type:
int_: Default integer type (same as C long; normally either int64 or int32)
For windows systems, longs are 32bit, even on 64bit builds (see here for more) so that's what's used by default, int32.
As DeepSpace suggested, setting dtype to int64 does the trick. This can be done either in arange or in the sum method.
Additionally, you wrote:
Before posting, I wrote the following, which returns True:
np.arange(1,65536).sum() == ((65535+1) * 65535)/2
However, the number 65536 seems to be a critical point, as
np.arange(1,65537).sum() == ((65536+1) * 65536)/2
returns False.
and this is explained by the fact that the second sum exceeds int32's max value while the first doesn't:
>> np.arange(1,65536).sum() < np.iinfo(np.int32).max
True
>>> np.arange(1,65537).sum() < np.iinfo(np.int32).max
False
of course the Python calculation is correct due to Python 3's arbitrary precision ints.
This is why many of us weren't able to reproduce. On most Unixes the default int size for 64bit machines is int64 (since the C long is 64bits) therefore the sum of those ints was equal to the expected value.

Why Lua and Python factorial output was different

--t.lua
function fact(n)
if n == 0 then
return 1
else
return n * fact(n-1)
end
end
for i=1,100,1 do
print(i,fact(i))
end
# t.py
fact = lambda n:1 if n == 0 else n * fact(n-1)
for i in range(1, 100):
print(i, fact(i))
When I write a factorial code in Lua and in Python, I found that output was different.
Lua as usually configured uses your platform's usual double-precision floating point format to store all numbers (this means all number types). For most desktop platforms today, that will be the 64-bit IEEE-754 format. The conventional wisdom is that integers in the range -1E15 to +1E15 can be safely assumed to be represented exactly. To deal with huge numbers in Lua, key words are "bignum" and "arbitrary precision numbers". You can use pure-Lua modules. for example (bignum and lua-nums) and C-based module lmapm. Also read this thread.
Python supports a such-known "bignum" integer type which can work with arbitrarily large numbers. In Python 2.5+, this type is called long and is separate from the int type, but the interpreter will automatically use whichever is more appropriate. In Python 3.0+, the int type has been dropped completely. In Python usually you don't need to use special tools to deal with huge numbers.
This is basic example with lbn library library
local bn = require "bn"
function bn_fact(n)
if n:tonumber() == 0 then return 1 end
return n * bn_fact(n-1)
end
function fact(n)
return bn_fact(bn.number(n))
end
for i=1,100,1 do
print(i,fact(i))
end
Output for some values
30 265252859812191058636308480000000
31 8222838654177922817725562880000000
32 263130836933693530167218012160000000
33 8683317618811886495518194401280000000
You have an overflow on your first image because values are to big to be stored on that var.

Positive integer from Python hash() function

I want to use the Python hash() function to get integer hashes from objects. But built-in hash() can give negative values, and I want only positive. And I want it to work sensibly on both 32-bit and 64-bit platforms.
I.e. on 32-bit Python, hash() can return an integer in the range -2**31 to 2**31 - 1.
On 64-bit systems, hash() can return an integer in the range -2**63 to 2**63 - 1.
But I want a hash in the range 0 to 2**32-1 on 32-bit systems, and 0 to 2**64-1 on 64-bit systems.
What is the best way to convert the hash value to its equivalent positive value within the range of the 32- or 64-bit target platform?
(Context: I'm trying to make a new random.Random style class. According to the random.Random.seed() docs, the seed "optional argument x can be any hashable object." So I'd like to duplicate that functionality, except that my seed algorithm can't handle negative integer values, only positive.)
Using sys.maxsize:
>>> import sys
>>> sys.maxsize
9223372036854775807L
>>> hash('asdf')
-618826466
>>> hash('asdf') % ((sys.maxsize + 1) * 2)
18446744073090725150L
Alternative using ctypes.c_size_t:
>>> import ctypes
>>> ctypes.c_size_t(hash('asdf')).value
18446744073090725150L
Just using sys.maxsize is wrong for obvious reasons (it being `2*n-1 and not 2*n), but the fix is easy enough:
h = hash(obj)
h += sys.maxsize + 1
for performance reasons you may want to split the sys.maxsize + 1 into two separate assignments to avoid creating a long integer temporarily for most negative numbers. Although I doubt this is going to matter much
(Edit: at first I thought you always wanted a 32-bit value)
Simply AND it with a mask of the desired size. Generally sys.maxsize will already be such a mask, since it's a power of 2 minus 1.
import sys
assert (sys.maxsize & (sys.maxsize+1)) == 0 # checks that maxsize+1 is a power of 2
new_hash = hash & sys.maxsize
How about:
h = hash(o)
if h < 0:
h += sys.maxsize
This uses sys.maxsize to be portable between 32- and 64-bit systems.

Categories

Resources