Python 中十六进制数的补码

问题描述 投票:0回答:7

a 和b(十六进制)下方,表示二进制补码有符号二进制数。 例如:

a = 0x17c7cc6e
b = 0xc158a854

现在我想知道以 10 为基数的 a 和 b 的符号表示。觉得问这个很傻。我不关心额外的图书馆,但答案应该简单明了。背景:a 和 b 是从 UDP 数据包中提取的数据。我无法控制格式。所以请不要给我一个假设我可以事先更改这些变量格式的答案。

我已经将 a 和 b 转换为以下内容:

aBinary = bin(int(a, 16))[2:].zfill(32) => 00010111110001111100110001101110 => 398969966 bBinary = bin(int(b, 16))[2:].zfill(32) => 11000001010110001010100001010100 => -1051154348

我正在尝试做这样的事情(不起作用):

if aBinary[1:2] == 1: aBinary = ~aBinary + int(1, 2)

在 python 中执行此操作的正确方法是什么?

python python-2.7 binary hex
7个回答
10
投票
为什么不使用

ctypes

>>> import ctypes >>> a = 0x17c7cc6e >>> ctypes.c_int32(a).value 398969966 >>> b = 0xc158a854 >>> ctypes.c_int32(b).value -1051154348
    

7
投票
在 Python 中执行此操作的一个好方法是使用按位运算。例如,对于 32 位值:

def s32(value): return -(value & 0x80000000) | (value & 0x7fffffff)

将此应用于您的价值观:

>>> s32(a) 398969966 >>> s32(b) -1051154348

此函数的作用是对值进行符号扩展,以便使用正确的符号和值正确解释它。

Python 有点棘手,因为它使用任意精度的整数,因此负数被视为有无限系列的前导 1 位。例如:

>>> bin(-42 & 0xff) '0b11010110' >>> bin(-42 & 0xffff) '0b1111111111010110' >>> bin(-42 & 0xffffffff) '0b11111111111111111111111111010110'
    

6
投票
>>> import numpy >>> numpy.int32(0xc158a854) -1051154348
    

4
投票
您至少必须知道数据的宽度。例如,0xc158a854 有 8 个十六进制数字,因此它必须至少有 32 位宽;它似乎是一个无符号的 32 位值。我们可以使用一些位运算来处理它:

In [232]: b = 0xc158a854 In [233]: if b >= 1<<31: b -= 1<<32 In [234]: b Out[234]: -1051154348L

这里的 L 表示 Python 2 已经切换到 long 处理值;它通常并不重要,但在这种情况下表明我一直在使用此安装的公共 int 范围之外的值。从UDP包等二进制结构中提取数据的工具是

struct.unpack;如果你只是告诉它你的值首先是有符号的,它会产生正确的值:

In [240]: s = '\xc1\x58\xa8\x54' In [241]: import struct In [242]: struct.unpack('>i', s) Out[242]: (-1051154348,)

假设二进制补码表示;一个的补码(例如 UDP 中使用的校验和)、符号和大小或 IEEE 754 浮点数是一些不太常见的数字编码。


1
投票
另一个现代解决方案:

>>> h = 0xc158a854 >>> int.from_bytes(bytes.fromhex(hex(h)[2:]), byteorder='big', signed=True) -1051154348
    

0
投票
2^31 = 0x80000000(符号位,二进制补码表示-2^31)

2^31-1 = 0x7fffffff(所有正位)

因此 (n & 0x7fffffff) - (n & 0x80000000) 将正确应用符号

你甚至可以这样做,n - ((n & 0x80000000)

<<1) to subtract the msb value twice

或者最后有 (n & 0x7fffffff) | -(n & 0x80000000) 只是合并负位,而不是减去

def signedHex(n): return (n & 0x7fffffff) | -(n & 0x80000000) signedHex = lambda n: (n & 0x7fffffff) | -(n & 0x80000000)
    

0
投票
value=input("enter hexa decimal value for getting compliment values:=") highest_value="F"*len(value) resulting_decimal=int(highest_value,16)-int(value,16) ones_compliment=hex(resulting_decimal) twos_compliment=hex(r+1) print(f'ones compliment={ones_compliment}\n twos complimet={twos_compliment}')
    
© www.soinside.com 2019 - 2024. All rights reserved.