I'm using python 2.7, numpy 1.6.1, 32-bit on windows. I'm writing a function to pack some data into 32-bit integers and generating C source declarations from the constant values. In doing so, I found some strange behavior in numpy's uint8 type.
No one is surprised, I'm sure, to see this:
>>> n = 0x94 << 24
>>> n
2483027968L
>>> hex(n)
'0x94000000L'
But do the same with a numpy uint8, and you get something that surprised me:
>>> n = np.uint8(0x94) << 24
>>> n
-1811939328
>>> hex(n)
'-0x6c000000'
One would think an explicitly unsigned type would be even less likely to return a negative value.
Note that values with the sign-bit clear work as expected:
>>> n = np.uint8(0x74) << 24
>>> n; hex(n)
1946157056
'0x74000000'
I happen to notice that numpy seems to be promoting unsigned types to signed types:
>>> n = np.uint8(0x74) << 24
>>> type(n)
<type 'numpy.int32'>
That seems a clear bug. I can find no reference to such a known bug, but...is it?
numpy
appears to treat the right-hand argument (24
) as a signed integer of the native width (int32
in your case, int64
in mine).
It looks like the uint8
gets promoted to the same type, and the result of the shift is also of the same type:
>>> np.uint8(0x94) << 56
-7782220156096217088
>>> type(np.uint8(0x94) << 56)
<type 'numpy.int64'>
Making the right-hand argument into an unsigned int
gives the result you expect:
>>> np.uint8(0x94) << np.uint(56)
10664523917613334528
>>> type(np.uint8(0x94) << np.uint(56))
<type 'numpy.uint64'>
>>> hex(np.uint8(0x94) << np.uint(56))
'0x9400000000000000L'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With