16位十六进制到14位签名int python?

时间:2016-09-17 23:04:40

标签: python cut bits data-conversion

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

实际上,这个数字只有14位,前两位(左起)是无关紧要的。 我试图这样做(在Python 3中)但很难失败。 任何建议如何" cut"数字的前两位数,然后使其余的有符号整数? 数据表说,E002应为-8190,1FFE应为+8190。

非常感谢!

2 个答案:

答案 0 :(得分:2)

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

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

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

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

有符号数字的通常惯例是,如果设置高位,则数字为负数,如果不设置则为正数。遵循此约定,'0000'为零,'FFFF'为-1。问题是int假设一个数字是正数,我们必须纠正:

  • 对于任何等于或小于0x7FFF的数字,则取消设置高位且数字为正。因此,如果r&lt; 2 ** 15。

  • ,我们将返回r=int(x,16)
  • 对于任何等于或大于r-int(x,16)的{​​{1}},我们都会返回0x8000

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

替代

我们可以直接测试r - 2**16中的高位是否设置,而不是将x转换为r并测试r的值:

x

忽略高位

假设制造商没有遵循标准惯例,并且高2位是不可靠的。在这种情况下,我们可以使用modulo >>> def g(x): ... return int(x, 16) if x[0] in '01234567' else int(x, 16) - 2**16 ... >>> g('1FFE') 8190 >>> g('E002') -8190 来删除它们,并在调整了适合14位整数的其他常量后,我们有:

%

答案 1 :(得分:1)

有一种通用算法用于对2位补码整数值val进行符号扩展,其位数为nbits(因此这些位的最顶部是符号位)。

该算法是:

  1. 将该值视为非负数,并在需要时屏蔽其他位
  2. 反转符号位,仍然将结果视为非负数
  3. 减去被视为非负数的符号位的数值,结果产生签名的号。
  4. 在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