import ctypes
number = lv & 0xFFFFFFFF
signed_number = ctypes.c_long(number).value
Answer from Raony Barrios on Stack Overflowimport ctypes
number = lv & 0xFFFFFFFF
signed_number = ctypes.c_long(number).value
Essentially, the problem is to sign extend from 32 bits to... an infinite number of bits, because Python has arbitrarily large integers. Normally, sign extension is done automatically by CPU instructions when casting, so it's interesting that this is harder in Python than it would be in, say, C.
By playing around, I found something similar to BreizhGatch's function, but that doesn't require a conditional statement. n & 0x80000000 extracts the 32-bit sign bit; then, the - keeps the same 32-bit representation but sign-extends it; finally, the extended sign bits are set on n.
def toSigned32(n):
n = n & 0xffffffff
return n | (-(n & 0x80000000))
Bit Twiddling Hacks suggests another solution that perhaps works more generally. n ^ 0x80000000 flips the 32-bit sign bit; then - 0x80000000 will sign-extend the opposite bit. Another way to think about it is that initially, negative numbers are above positive numbers (separated by 0x80000000); the ^ swaps their positions; then the - shifts negative numbers to below 0.
def toSigned32(n):
n = n & 0xffffffff
return (n ^ 0x80000000) - 0x80000000
I have an integer from the result of binascii.crc32(). In Python 2, this function returned a signed int. However, in Python 3, it has been changed to always return an unsigned int. I am porting a piece of software from 2 to 3, and one of the things it does is calculate the crc and pack it with struct.pack(">l", crc32). This now causes an error as ">l" expects -2147483648 <= number <= 2147483647 but the crc can now exceed the upper limit.
How would I go about converting the crc to a signed value? As I understand Python doesn't have a concept of signed/unsigned, so you can't do signed_int = (int)unsigned_int; like you can in C.
I have a string (list member) that's being received as 65520, for instance. However this value is being received from a register that's a regular INT 2's complement representation. So really it's -16 in disguise. Obviously that's a problem on the sending side, when it does the INT to ASCII it should just encode it as -16, but it doesn't/can't.
When I read this value into an INT it of course reads the INT as 65520 since it has no way of knowing the original representation. Is there a way to force the ASCII to INT conversion to interpret the string value as a signed INT? So that input string = 65520 outputs INT = -16?
Not sure if it's "nicer" or not...
import ctypes
def int32_to_uint32(i):
return ctypes.c_uint32(i).value
using numpy for example:
import numpy
result = numpy.uint32( numpy.int32(myval) )
or even on arrays,
arr = numpy.array(range(10))
result = numpy.uint32( numpy.int32(arr) )