将两个字节组合成有符号值(16 位)

Posted

技术标签:

【中文标题】将两个字节组合成有符号值(16 位)【英文标题】:combine two bytes to form signed value (16 bit) 【发布时间】:2022-01-17 15:35:00 【问题描述】:

我想将两个字节(8 bit)按照二补的方法组合成一个有符号值(one bit for sign and 15 for the value)。 我收到MSbyte(注意MSByte 的最左边是符号)和LSbyte。所以我通过将MSByte向左移动8 bit来编写一个函数,然后我将它与LSByte相加,形成16 bit的二进制序列。然后,我计算ones'complement,最后将结果加1。但是,它不起作用。

def twos_comp_two_bytes(msb, lsb):
    a= (msb<<8)+ lsb
    r = ~(a)+1
    return r

例如 0b0b1111110111001001-567 但是使用上述函数我得到 -64969

编辑:函数调用

twos_comp_two_bytes(0b11111101,0b11001001) => -64969
 

【问题讨论】:

您考虑过使用bytearray吗?例如bytearray(msb+lsb) 您的数据是bytesint 还是其他? 我的数据是0b....'的形式 0b....(整数)还是'0b....'(字符串)? 我在我的代码中收到了用于 MSB 的 bytearray(1) 和用于 LSB 的 bytearray(1) 【参考方案1】:

Python 使用可能有任何长度的整数 - 它们不限于 16bits,因此要获得 -567,它需要宁可

r = a - (256*256)

但其他值需要更多代码

def twos_comp_two_bytes(msb, lsb):
    a = (msb<<8) + lsb
    if a >= (256*256)//2:
        a = a - (256*256)
    return a

print(twos_comp_two_bytes(0b11111101, 0b11001001))
print(twos_comp_two_bytes(0b0, 0b0))
print(twos_comp_two_bytes(0b0, 0b1))
print(twos_comp_two_bytes(0b10000000, 0b0))
print(twos_comp_two_bytes(0b10000000, 0b1))

结果:

-567
0
1
-32768
-32767

为此最好使用特殊模块struct

import struct

def twos_comp_two_bytes(msb, lsb):
    return struct.unpack('>h', bytes([msb, lsb]))[0]  
    #return struct.unpack('<h', bytes([lsb, msb]))[0] # different order `[lsb, msb]`
    #return struct.unpack( 'h', bytes([lsb, msb]))[0] # different order `[lsb, msb]`

print(twos_comp_two_bytes(0b11111101, 0b11001001))
print(twos_comp_two_bytes(0b0, 0b0))
print(twos_comp_two_bytes(0b0, 0b1))
print(twos_comp_two_bytes(0b10000000, 0b0))
print(twos_comp_two_bytes(0b10000000, 0b1))

结果:

-567
0
1
-32768
-32767

字母h 表示short integer(签名int 2 个字节)。

Char &gt;, &lt; 描述字节顺序。

在Format Characters中查看更多信息

【讨论】:

以上是关于将两个字节组合成有符号值(16 位)的主要内容,如果未能解决你的问题,请参考以下文章

c和指针

将两个 Int32 组合成一个 Int64

将打包的半字节组合成打包的字节

将 2 个字节转换为有符号 16 位整数的正确方法是啥?

将 2 个连续字节转换为一个 int 值在 C# 中提高速度

如何将两个每个 8 位的数组(二进制数字字符串组合成一个 16 位的单个字符串?(arduino,移位寄存器)