Python integer overflow simulation

Python 2 has two integer data types, int and long and automatically converts them as needed, especially to avoid integer overflows.

I mimic a C function in Python and wonder if there are standard ways to re-enable integer overflows. For nonce I used

 overflow_point = maxint + 1 if value > overflow_point: value -= 2 * overflow_point 

Is there a more standard way to do the same?

+6
source share
4 answers

I think the basic idea sounds, but needs some tweaks:

  • your function does not overflow on sys.maxint+1 , but it should;
  • sys.maxint can be exceeded several times as a result of one operation;
  • negative values โ€‹โ€‹below -sys.maxint-1 must also be considered.

With that in mind, I came up with the following:

 import sys def int_overflow(val): if not -sys.maxint-1 <= val <= sys.maxint: val = (val + (sys.maxint + 1)) % (2 * (sys.maxint + 1)) - sys.maxint - 1 return val 
+9
source

This function should convert your numbers so that they look like hardware integers. Depending on your application, you may need to apply this function between each step of your operations.

 def correct(value, bits, signed): base = 1 << bits value %= base return value - base if signed and value.bit_length() == bits else value 

The following quick access functions may be useful for cast values โ€‹โ€‹in the appropriate range:

 byte, sbyte, word, sword, dword, sdword, qword, sqword = ( lambda v: correct(v, 8, False), lambda v: correct(v, 8, True), lambda v: correct(v, 16, False), lambda v: correct(v, 16, True), lambda v: correct(v, 32, False), lambda v: correct(v, 32, True), lambda v: correct(v, 64, False), lambda v: correct(v, 64, True) ) 

As an example of how you can use them, you can reproduce the error that can be seen in C. If you need to write a for loop using print bytes 0 - 255, the cycle will never end. The following program demonstrates this problem:

 #! /usr/bin/env python3 def main(): counter = 0 while counter < 256: print(counter) counter = byte(counter + 1) def correct(value, bits, signed): base = 1 << bits value %= base return value - base if signed and value.bit_length() == bits else value byte, sbyte, word, sword, dword, sdword, qword, sqword = ( lambda v: correct(v, 8, False), lambda v: correct(v, 8, True), lambda v: correct(v, 16, False), lambda v: correct(v, 16, True), lambda v: correct(v, 32, False), lambda v: correct(v, 32, True), lambda v: correct(v, 64, False), lambda v: correct(v, 64, True) ) if __name__ == '__main__': main() 
+6
source

Does your function use division or proper bit offset? If not, then you do not need to worry about overflows at each stage of the calculation, because you will always get the โ€œcorrectโ€ answer modulo 2 ^ 32 or 2 ^ 64. Before returning the result (or before doing the division or right shift of the bit) you can normalize back to standard integer range using something like

 import sys HALF_N = sys.maxint + 1 N = HALF_N * 2 def normalize(value): return (value + HALF_N) % N - HALF_N 
+4
source

I do not know that there is a convenient way to do this initially, because it is usually not considered a problem, therefore it is not something that python developers would like to embed. I think you are doing it fine. You can even subclass the built-in int type and override the __add__() , __sub__() , etc. methods to enable your functionality, but this may be redundant.

+3
source

Source: https://habr.com/ru/post/899316/


All Articles