简体   繁体   English

将16位十六进制转换为14位带符号的int python?

[英]16 bit hex into 14 bit signed int python?

I get a 16 bit Hex number (so 4 digits) from a sensor and want to convert it into a signed integer so I can actually use it. 我从传感器获取一个16位十六进制数字(即4位数字),并希望将其转换为有符号整数,以便我可以实际使用它。 There are plenty of codes on the internet that get the job done, but with this sensor it is a bit more arkward. 互联网上有很多代码可以完成工作,但是有了这个传感器,它就显得有些尴尬了。

In fact, the number has only 14 bit, the first two (from the left) are irrelevant. 实际上,数字只有14位,前两位(从左开始)是无关紧要的。 I tried to do it (in Python 3) but failed pretty hard. 我试图做到这一点(在Python 3中),但失败相当艰巨。 Any suggestions how to "cut" the first two digits of the number and then make the rest a signed integer? 有什么建议如何“削减”数字的前两位数字,然后使其余数字成为有符号整数? The Datasheet says, that E002 should be -8190 ane 1FFE should be +8190. 数据表说,E002应该是-8190,而1FFE应该是+8190。

Thanks a lot! 非常感谢!

Let's define a conversion function: 让我们定义一个转换函数:

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

Now, let's test the function against the values that the datahsheet provided: 现在,让我们对照数据表提供的值测试该函数:

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

The usual convention for signed numbers is that a number is negative if the high bit is set and positive if it isn't. 对于带符号的数字,通常的约定是:如果设置了高位,则数字为负;如果未设置高位,则为正。 Following this convention, '0000' is zero and 'FFFF' is -1. 按照该约定,“ 0000”为零,“ FFFF”为-1。 The issue is that int assumes that a number is positive and we have to correct for that: 问题是int假设数字是正数,我们必须对此进行更正:

  • For any number equal to or less than 0x7FFF , then high bit is unset and the number is positive. 对于等于或小于0x7FFF任何数字,则高位未设置并且该数字为正。 Thus we return r=int(x,16) if r<2**15. 因此r=int(x,16)如果r <2 ** 15 r=int(x,16)则返回r=int(x,16)

  • For any number r-int(x,16) that is equal to or greater than 0x8000 , we return r - 2**16 . 对于等于或大于0x8000任何数字r-int(x,16) ,我们返回r - 2**16

  • While your sensor may only produce 14-bin data, the manufacturer is following the standard convention for 16-bit integers. 虽然您的传感器只能产生14档数据,但制造商正在遵循16位整数的标准约定。

Alternative 另类

Instead of converting x to r and testing the value of r , we can directly test whether the high bit in x is set: 相反转换的xr和测试的价值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

Ignoring the upper bits 忽略高位

Let's suppose that the manufacturer is not following standard conventions and that the upper 2-bits are unreliable. 让我们假设制造商未遵循标准约定,并且高2位不可靠。 In this case, we can use modulo, % , to remove them and, after adjusting the other constants as appropriate for 14-bit integers, we have: 在这种情况下,我们可以使用%取模,然后将它们调整为适合于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

There is a general algorithm for sign-extending a two's-complement integer value val whose number of bits is nbits (so that the top-most of those bits is the sign bit). 存在一种通用的算法,用于对位数为nbits位的二进制补码整数值val进行符号扩展(因此,这些位的最高位是符号位)。

That algorithm is: 该算法是:

  1. treat the value as a non-negative number, and if needed, mask off additional bits 将值视为非负数,并在需要时屏蔽掉其他位
  2. invert the sign bit, still treating the result as a non-negative number 反转符号位,仍将结果视为非负数
  3. subtract the numeric value of the sign bit considered as a non-negative number, producing as a result, a signed number. 减去被认为是非负数的符号位的数值,从而产生一个符号数。

Expressing this algorithm in Python produces: 在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))

which when run shows the desired results: 运行时显示出预期的结果:

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

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

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