Crazy Clyde
Crazy Clyde

Reputation: 57

Bitwise shift returns unexpected value in Python

I'm performing 55 << 30 in C# and Python 3. C# returns -1073741824, which is what I want, but Python returns 59055800320. Can someone explain why exactly this happens, and what I can do to fix it?

Upvotes: 0

Views: 196

Answers (3)

Mark Tolonen
Mark Tolonen

Reputation: 178179

Python integers are unbounded, so 59055800320 is the correct answer, but to simulate C#'s 32-bit limitation on integers and 2s complement negative numbers, you can do the math:

>>> hex(55)
'0x37'
>>> hex(55 << 30)  # 36-bit result, too large for 32-bit integers
'0xdc0000000'
>>> hex(55 << 30 & 0xffffffff) # mask off lower 32 bits.
'0xc0000000'
>>> ((55 << 30) & 0xffffffff)  # but the sign (bit 31) is a one, so it should be negative
3221225472

Bit 31 in a 32-bit signed integer has value -231, but unsigned it has value 231, meaning the value is 232 too high, so:

>>> ((55 << 30) & 0xffffffff) - (1<<32)
-1073741824

Here's a function:

def signed_32bit_shift_left(n,s):
    tmp = (n << s) & 0xffffffff
    return tmp - (1<<32) if tmp & 0x80000000 else tmp

Upvotes: 1

Daniel
Daniel

Reputation: 2469

As the others have said, Python ints are much larger than you might expect. To observe this (Python 3.7.4):

>>> import sys
>>> type(55)
<class 'int'>
>>> sys.getsizeof(int())
24

sys.getsizeof() will return the size, in bytes, of an object in memory.

Upvotes: 0

Joran Beasley
Joran Beasley

Reputation: 114088

python ints are arbitrarily large ... you can force it sort of

import numpy

numpy.int32(55) << 30

Upvotes: 1

Related Questions