2014-10-29 57 views
3

下面的a和b(十六进制)表示二进制补码带符号的二进制数。 例如:Python中十六进制数的二进制补码

a = 0x17c7cc6e 
b = 0xc158a854 

现在我想知道一个& B在底部的符号表示10对不起,我低水平程序员,新的Python;感到非常愚蠢的问这个问题。我不在乎额外的图书馆,但答案应该简单而直接。背景:一个&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中做到这一点?

回答

2

您必须至少知道数据的宽度。例如,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已切换到加工值作为长;它通常并不重要,但在这种情况下,表明我一直在使用公共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浮点数是一些不太常用的编码编码。

+0

谢谢!第一种方法效果很好,它是一个没有库+1的单线程。 – Nimjox 2014-10-29 23:02:51

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

在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' 
相关问题