【问题标题】:16 bit hex into 14 bit signed int python?16 位十六进制转换为 14 位有符号整数 python?
【发布时间】:2016-09-17 23:04:40
【问题描述】:

我从传感器获得一个 16 位十六进制数(即 4 位数字),并希望将其转换为有符号整数,以便实际使用它。 互联网上有很多代码可以完成这项工作,但有了这个传感器,它就有点难了。

其实这个数字只有 14 位,前两位(左起)无关紧要。 我试图做到这一点(在 Python 3 中)但非常失败。 有什么建议如何“剪切”数字的前两位数字,然后将其余数字设为有符号整数? 数据表上说,E002 应该是 -8190,而 1FFE 应该是 +8190。

非常感谢!

【问题讨论】:

  • 附带说明:“数字”不是正确的术语。这是为十进制数字保留的(不是​​十六进制)
  • 感谢您纠正我下沉点!我不是母语人士,据我所知,我们对不同的数字系统没有不同的术语,所以我没有考虑过。很高兴知道,总是很高兴学习一些东西;)

标签: python cut bits data-conversion


【解决方案1】:

让我们定义一个转换函数:

>>> def f(x):
...    r = int(x, 16)
...    return r if r < 2**15 else r - 2**16
... 

现在,让我们根据数据表提供的值来测试函数:

>>> f('1FFE')
8190
>>> f('E002')
-8190

有符号数的通常约定是,如果设置了高位,则数字为负数,否则为正数。按照这个约定,“0000”为零,“FFFF”为-1。问题是int 假设一个数字是正数,我们必须纠正它:

  • 对于等于或小于0x7FFF 的任何数字,则未设置高位并且该数字为正数。因此,如果 rr=int(x,16)。

  • 对于任何等于或大于0x8000 的数字r-int(x,16),我们返回r - 2**16

  • 虽然您的传感器可能只产生 14 位数据,但制造商遵循 16 位整数的标准约定。

另类

不用将x转换成r再测试r的值,我们可以直接测试x中的高位是否设置:

>>> def g(x):
...    return int(x, 16) if x[0] in '01234567' else int(x, 16) - 2**16
... 
>>> g('1FFE')
8190
>>> g('E002')
-8190

忽略高位

假设制造商没有遵循标准约定,并且高 2 位不可靠。在这种情况下,我们可以使用取模 % 来删除它们,并且在根据 14 位整数调整其他常量之后,我们有:

>>> def h(x):
...    r = int(x, 16) % 2**14
...    return r if r < 2**13 else r - 2**14
... 
>>> h('1FFE')
8190
>>> h('E002')
-8190

【讨论】:

  • 您将(至少可能)用 14 位数在这里遇到的问题是位 0xc000 应该被忽略,所以虽然 0xe002 是 -8190,所以是 0x2002。如果第 14 位和第 15 位是符号位(第 13 位)的副本,则可以将其视为带符号的 16 位二进制补码值。
  • @torek 真的。除非制造商说 E002 是 -8190,否则我会担心这一点:换句话说,它们遵循 16 位整数的标准约定。
  • @torek 为了完整起见,我只是添加了忽略高 2 位的代码
  • 非常感谢您解决了我的问题以及您的解释!
【解决方案2】:

有一种通用算法可以对二进制补码整数值val 进行符号扩展,其位数为nbits(因此这些位的最高位是符号位)。

那个算法是:

  1. 将该值视为非负数,如果需要,屏蔽其他位
  2. 反转符号位,仍将结果视为非负数
  3. 减去被视为非负数的符号位的数值,结果是一个有符号数。

用 Python 表达这个算法会产生:

from __future__ import print_function

def sext(val, nbits):
    assert nbits > 0
    signbit = 1 << (nbits - 1)
    mask = (1 << nbits) - 1
    return ((val & mask) ^ signbit) - signbit

if __name__ == '__main__':
    print('sext(0xe002, 14) =', sext(0xe002, 14))
    print('sext(0x1ffe, 14) =', sext(0x1ffe, 14))

运行时会显示所需的结果:

sext(0xe002, 14) = -8190
sext(0x1ffe, 14) = 8190

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-09
    • 2014-04-11
    • 2014-05-05
    • 1970-01-01
    • 1970-01-01
    • 2011-04-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多