Python中二进制数的二进制补码

时间:2014-10-29 22:20:41

标签: python python-2.7 binary hex

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

a = 0x17c7cc6e
b = 0xc158a854

现在我想知道一个&的签名代表。基地10中的b。抱歉,我是一名低级程序员,不熟悉python;问这个问题感觉非常愚蠢。我不关心额外的图书馆,但答案应该简单明了。背景:a& b是从UDP分组中提取的数据。我无法控制格式。所以请不要给我一个答案,假设我可以事先改变那些变量的格式。

我转换了一个& 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中执行此操作的正确方法是什么?

6 个答案:

答案 0 :(得分:3)

>>> import numpy
>>> numpy.int32(0xc158a854)
-1051154348

答案 1 :(得分:3)

您必须至少知道数据的宽度。例如,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浮点数是一些不太常见的数字编码。

答案 2 :(得分:3)

在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'

答案 3 :(得分:1)

为什么不使用ctypes

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

答案 4 :(得分:0)

2 ^ 31 = 0x80000000(符号位,在两个符号中表示-2 ^ 31)
2 ^ 31-1 = 0x7fffffff(所有正位)

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

你甚至可以这样做,n - ((n&amp; 0x80000000)&lt;&lt; 1)两次减去msb值

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

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

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

答案 5 :(得分: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}')