【发布时间】:2016-03-11 13:11:48
【问题描述】:
为了说明我的意思:在十六进制编辑器中,我有8C 01,即396 little-endian。我正在使用的数据是一个包含两个单独的 8 位整数 i = (140, 1) 的元组。
要计算 16 位值,我的第一种方法是简单地将第二个整数乘以 255,然后将第一个整数相加。然而,这种方法是完全错误的,因为它没有给出正确的值(由于我缺乏知识)。谁能提供更好的(可能是 Pythonic)方法?
【问题讨论】:
为了说明我的意思:在十六进制编辑器中,我有8C 01,即396 little-endian。我正在使用的数据是一个包含两个单独的 8 位整数 i = (140, 1) 的元组。
要计算 16 位值,我的第一种方法是简单地将第二个整数乘以 255,然后将第一个整数相加。然而,这种方法是完全错误的,因为它没有给出正确的值(由于我缺乏知识)。谁能提供更好的(可能是 Pythonic)方法?
【问题讨论】:
您需要将它乘以 256 (28)。所以函数应该是这样的:
def pack (tup) :
return 256*tup[1]+tup[0]
或执行bitwise shift,这在使用位时更有意义:
def pack(tup) :
return (tup[1]<<8)|tup[0]
这里<< 表示您将tup[1] 的值放在左边八个位置。管道 (|) 表示您执行 OR 操作。如果您强制元组中的值小于 256 并且可以 - 至少在理论上 - 导致一些加速,这是合理的。
如果您的元组具有任意长度(例如三个、四个或更多元素),您可以定义一个更通用的函数:
def pack(tup) :
sum = 0
for i in range(len(tup)) :
sum |= tup[i]<<(i<<3)
return sum
这里<<3 用作与8 相乘的快捷方式,因此等效函数为:
def pack(tup) :
sum = 0
for i in range(len(tup)) :
sum |= tup[i]<<(8*i)
return sum
或者写出来,是这样的:
tup[0]|(tup[1]<<8)|(tup[2]<<16)|(...)
【讨论】:
256 的幂。因此,对于三个项目,您可以将其计算为 65536*tup[2]+256*tup[1]+tup[0] 或 (tup[2]<<16)|(tup[1]<<8)|tup[0]。该函数使用<<3 代替与8 相乘。
tup[0]|(tup[1]<<3)|(tup[2]<<6)|(tup[3]<<9)|(...)?出于某种原因,我对此进行的编辑违反了本网站的编辑规则并被拒绝。
tup[0]|(tup[1]<<8)|...,所以有八跳。 <<3 应用于第一个代码示例中的 i,将其乘以 8(乘以 8 与向左移动三位相同)。
你应该乘以 256...
>>> i[1]*256 + i[0]
396
有一种使用struct模块的Python方式,但在这种简单的情况下不是必需的。
>>> from struct import pack, unpack
>>> unpack('<H', pack('BB', *i))[0]
396
【讨论】: