Assuming:
- You have 2's-complement representations in mind; and,
- By
(unsigned long)you mean unsigned 32-bit integer,
then you just need to add 2**32 (or 1 << 32) to the negative value.
For example, apply this to -1:
>>> -1
-1
>>> _ + 2**32
4294967295L
>>> bin(_)
'0b11111111111111111111111111111111'
Assumption #1 means you want -1 to be viewed as a solid string of 1 bits, and assumption #2 means you want 32 of them.
Nobody but you can say what your hidden assumptions are, though. If, for example, you have 1's-complement representations in mind, then you need to apply the ~ prefix operator instead. Python integers work hard to give the illusion of using an infinitely wide 2's complement representation (like regular 2's complement, but with an infinite number of "sign bits").
And to duplicate what the platform C compiler does, you can use the ctypes module:
>>> import ctypes
>>> ctypes.c_ulong(-1) # stuff Python's -1 into a C unsigned long
c_ulong(4294967295L)
>>> _.value
4294967295L
C's unsigned long happens to be 4 bytes on the box that ran this sample.
Assuming:
- You have 2's-complement representations in mind; and,
- By
(unsigned long)you mean unsigned 32-bit integer,
then you just need to add 2**32 (or 1 << 32) to the negative value.
For example, apply this to -1:
>>> -1
-1
>>> _ + 2**32
4294967295L
>>> bin(_)
'0b11111111111111111111111111111111'
Assumption #1 means you want -1 to be viewed as a solid string of 1 bits, and assumption #2 means you want 32 of them.
Nobody but you can say what your hidden assumptions are, though. If, for example, you have 1's-complement representations in mind, then you need to apply the ~ prefix operator instead. Python integers work hard to give the illusion of using an infinitely wide 2's complement representation (like regular 2's complement, but with an infinite number of "sign bits").
And to duplicate what the platform C compiler does, you can use the ctypes module:
>>> import ctypes
>>> ctypes.c_ulong(-1) # stuff Python's -1 into a C unsigned long
c_ulong(4294967295L)
>>> _.value
4294967295L
C's unsigned long happens to be 4 bytes on the box that ran this sample.
To get the value equivalent to your C cast, just bitwise and with the appropriate mask. e.g. if unsigned long is 32 bit:
>>> i = -6884376
>>> i & 0xffffffff
4288082920
or if it is 64 bit:
>>> i & 0xffffffffffffffff
18446744073702667240
Do be aware though that although that gives you the value you would have in C, it is still a signed value, so any subsequent calculations may give a negative result and you'll have to continue to apply the mask to simulate a 32 or 64 bit calculation.
This works because although Python looks like it stores all numbers as sign and magnitude, the bitwise operations are defined as working on two's complement values. C stores integers in twos complement but with a fixed number of bits. Python bitwise operators act on twos complement values but as though they had an infinite number of bits: for positive numbers they extend leftwards to infinity with zeros, but negative numbers extend left with ones. The & operator will change that leftward string of ones into zeros and leave you with just the bits that would have fit into the C value.
Displaying the values in hex may make this clearer (and I rewrote to string of f's as an expression to show we are interested in either 32 or 64 bits):
>>> hex(i)
'-0x690c18'
>>> hex (i & ((1 << 32) - 1))
'0xff96f3e8'
>>> hex (i & ((1 << 64) - 1)
'0xffffffffff96f3e8L'
For a 32 bit value in C, positive numbers go up to 2147483647 (0x7fffffff), and negative numbers have the top bit set going from -1 (0xffffffff) down to -2147483648 (0x80000000). For values that fit entirely in the mask, we can reverse the process in Python by using a smaller mask to remove the sign bit and then subtracting the sign bit:
>>> u = i & ((1 << 32) - 1)
>>> (u & ((1 << 31) - 1)) - (u & (1 << 31))
-6884376
Or for the 64 bit version:
>>> u = 18446744073702667240
>>> (u & ((1 << 63) - 1)) - (u & (1 << 63))
-6884376
This inverse process will leave the value unchanged if the sign bit is 0, but obviously it isn't a true inverse because if you started with a value that wouldn't fit within the mask size then those bits are gone.
Videos
How to maintain an unsignedness of number in python?
I have a function that takes an array of octets like so, swaps the bytes, and creates a number out of the array. The solution was seemingly easy with just:
def make_int(octets):
OCTET_SIZE = 8
num = 0
for i in range(len(octets)):
shift = OCTET_SIZE * i
num |= octets[i] << shift
return num
def main():
octets = [0x00, 0x10, 0xAB, 0xCE]
four_byte_value = make_int(octets)But this will occasionally fail and I don't know why. I'll randomly get 0xffffxx and that, to me, is indicative of a twos complement integer. What are potential pitfalls of function that I'm missing that's inducing this strange behavior?
SOLVED: 3 Solutions:
-
using Numpy : np.uint16()
-
Using CTypes : ctypes.c_uint16()
-
Using Bitwise : & 0xFFFF
Hi, I'm trying to convert this code to Python from Go / C. It involves declaring a UInt16 variable and run a bit shift operation. However cant seem to create a variable with this specific type. Need some advise here.
Go Code:
package main
import "fmt"
func main() {
var dx uint16 = 38629
var dy uint16 = dx << 8
fmt.Println(dy) //58624 -> Correct value
}
Python Code:
dx = 38629 dy = (dx << 8) print(dy) # 9889024 -> not the expected value print(type(dx)) # <class 'int'> print(type(dy)) # <class 'int'>
I cant seem to figure out a way to cast or similar function to get this into an Unsigned Int 16.\
Please help.
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?
id = int(hash) if (id & (1 << (32 - 1))) != 0: id = id - (1 << 32)
I was reading this repo and came upon this code block for converting a 64-bit unsigned integer into a 64-bit signed integer. I don't get what if (id& (1 << (32 - 1))) != 0 is for. What is it bit shifting left by 31 for? And why's it doing bitwise-and on it? Thank you for any help.
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) )
You can use ctypes and its c_uint32:
>>> import ctypes
>>> m = 0xFFFFFF00
>>> ctypes.c_uint32(~m).value
255L
So what I did here was casting ~m to a C 32-bit unsigned integer and retrieving its value back in Python format.
You can mask everything by 0xFFFFFFFF:
>>> m = 0xFFFFFF00
>>> allf = 0xFFFFFFFF
>>> ~m & allf
255L