Reputation: 3
I need some help. I am new to python. I am trying to accomplish the following which is written in C++ in python. Here is what I have:
C++:
uint16_t value = (ReadData[1] << 8 | ReadData[2]);
int num = (short) value;
int total = ((0.89*num)+48.31);
Python:
ReadData = [0]*6
arr = bytes(ReadData)
value = arr2[0:3]
Not sure how to take the array which is spit out like so:
b'\xff\xff\xce'
to a signed int.
Thank you in advance.
Upvotes: 0
Views: 75
Reputation: 155418
Since you're using bytes
and bytes
literals I'm guessing you're on Python 3, in which case you have a much better general option for converting arbitrary runs of bytes into an int
. Python 3 has an amazing all in one-converter. For your example case:
>>> int.from_bytes(b'\xff\xff\xce', 'big', signed=True)
-50
It scales to huge sizes, and runs faster than anything else available.
If you're not using Python 3, it's slightly uglier, but still fairly fast:
import binascii
def int_from_bytes(b):
x = int(binascii.hexlify(b), 16)
mask = 1 << (len(b) << 3) - 1
if x & mask:
x -= mask << 1
return x
Which gets the same results as the Python 3 built-in when you do:
>>> int_from_bytes(b'\xff\xff\xce')
-50
Note on performance: A pre-compiled struct.Struct
will win, hands down, if it's really as simple as one pad byte followed by a signed short
, no variable length nonsense. In that case, you'd precompile the Struct
with:
unpacker = struct.Struct('>xh').unpack
Then you can use it like so:
x, = unpacker(b'\xff\xff\xce')
The trailing comma is important (Struct.unpack
returns a len 1 tuple in this case, and assigning to x,
unpacks the single value into x
the most efficient way possible.
Upvotes: 2
Reputation: 4118
Use the struct
module to interpret a bytes string as C data.
If you want to interpret bytes 1 and 2 of ReadData
as big-endian signed 16-bit integar, do:
import struct
ReadData = b'\xff\xff\xce'
# ReadData[1:] takes from ReadData[1] until ReadData[-1] (the last one)
num = struct.unpack('>h', ReadData[1:])
# Now num is -50
Which would be equivalent to:
# Convert ReadData to unsigned int
num = (ReadData[1] & 0xFF) << 8 | (ReadData[2] & 0xFF)
# Change sign, assuming we got 16-bit number
num = num - 0x10000
Converting num
to total
should be trivial:
total = ((0.89*num)+48.31)
Note however that 0.89 * num
will cast it to float, so might want to do instead,
total = int((0.89 * num) + 48.31)
Upvotes: 0
Reputation: 114320
Python supports bitwise operations that are very similar to C++. If you have an array of Python int
s called ReadData
, you can do as follows:
value = (ReadData[1] & 0xFF) << 8 | (ReadData[2] & 0xFF)
total = ((0.89 * value) + 48.31)
The & 0xFF
removes everything but the lowest byte of the number, which appears to be what you want.
Upvotes: 0