CxTWICE
CxTWICE

Reputation: 3

Translating Array Manipulation in C++ to Python

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

Answers (3)

ShadowRanger
ShadowRanger

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

memoselyk
memoselyk

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

Mad Physicist
Mad Physicist

Reputation: 114320

Python supports bitwise operations that are very similar to C++. If you have an array of Python ints 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

Related Questions