简体   繁体   English

将 24 位整数转换为 32 位整数的更多 Pythonic 方式

[英]More Pythonic Way to Convert 24 bit ints to 32 bit ints

I currently use the following code to convert an array of bytes which represent little endian signed 24 bit integers into a list of signed 32 bit integers.我目前使用以下代码将表示 little endian 带符号 24 位整数的字节数组转换为带符号的 32 位整数列表。

xs = list(bytes_object)
ys = [xs[x:x+3] + [255] if xs[x+2] & 128 else xs[x:x+3] + [0]
      for x in range(0, len(xs), 3)]
int32s = [struct.unpack('<i', bytes(y))[0] for y in ys]

Is there a more pythonic or efficient way to handle the conversion?有没有更pythonic或更有效的方式来处理转换?

Of the top of my head, something like this:在我的头顶,是这样的:

import numpy as np

# First convert the buffer to an array of 3-vectors of uint8s
a3 = np.frombuffer(x, dtype=np.uint8).reshape(-1, 3)

# Now sign-extend it to an array of 4-vectors of uint8s
signs = (a3[..., 0] > 0x80) * 0xFF
a4 = np.concatenate((signs.reshape(-1, 1), a), axis=1)

# Now convert that to an array of int32s
i = a4.view(np.int32)

# And what you eventually wanted to do was convert to float64?
f = i.astype(np.float64)

I'm sure I've made at least one mistake (surely this won't work on a big-endian system, at least), and I don't have a computer with numpy installed in front of me, but hopefully that gets you started.我确信我至少犯了一个错误(这肯定不会在大端系统上工作,至少),而且我面前没有安装 numpy 的计算机,但希望能得到你开始了。 No need to do anything in a Python loop.无需在 Python 循环中执行任何操作。

outside of numpy, this is pretty pythonic:在 numpy 之外,这是非常 pythonic 的:

bytes_object = b'\x01\x00\x00\x00\x00\xf0'
[int.from_bytes(bytes_object[x:x+3], byteorder='little', signed=True) for x in range(0, len(bytes_object), 3)]

Here are my solutions.这是我的解决方案。 -8388608 -> FF80 0000 (32bit) or FFFF FFFF FF80 0000 (64bit) does the magic to convert the signed values. -8388608 -> FF80 0000 (32 位)或FFFF FFFF FF80 0000 (64 位)神奇地转换有符号值。

test_bytes = b'\x58\x18\x85'
def byte3toint(tmp, signed=True):
    b = tmp[0] | tmp[1] << 8 | tmp[2] << 16 # restore the bit represention
    if signed and tmp[2] & 128:
        b |= -8388608
    return b
assert byte3toint(test_bytes) == int.from_bytes(test_bytes, 'little', signed=True)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM