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

Nim*_*jox 7 python binary hex python-2.7

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

a = 0x17c7cc6e
b = 0xc158a854
Run Code Online (Sandbox Code Playgroud)

现在我想知道基数为 10 的 a & b 的有符号表示。抱歉,我是一名低级程序员,并且是 Python 新手;问这个问题感到很愚蠢。我不在乎额外的图书馆,但答案应该是简单明了的。背景: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
Run Code Online (Sandbox Code Playgroud)

我试图做这样的事情(不起作用):

if aBinary[1:2] == 1:
aBinary = ~aBinary + int(1, 2)
Run Code Online (Sandbox Code Playgroud)

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

Rom*_*man 7

为什么不使用ctypes

>>> import ctypes
>>> a = 0x17c7cc6e
>>> ctypes.c_int32(a).value
398969966
>>> b = 0xc158a854
>>> ctypes.c_int32(b).value
-1051154348
Run Code Online (Sandbox Code Playgroud)


Ign*_*ams 6

>>> import numpy
>>> numpy.int32(0xc158a854)
-1051154348
Run Code Online (Sandbox Code Playgroud)


dco*_*les 6

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

def s32(value):
    return -(value & 0x80000000) | (value & 0x7fffffff)?
Run Code Online (Sandbox Code Playgroud)

将此应用于您的价值观:

>>> s32(a)
398969966
>>> s32(b)
-1051154348
Run Code Online (Sandbox Code Playgroud)

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

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

>>> bin(-42 & 0xff)
'0b11010110'
>>> bin(-42 & 0xffff)
'0b1111111111010110'
>>> bin(-42 & 0xffffffff)
'0b11111111111111111111111111010110'
Run Code Online (Sandbox Code Playgroud)


Yan*_*ier 4

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

In [232]: b = 0xc158a854

In [233]: if b >= 1<<31: b -= 1<<32

In [234]: b
Out[234]: -1051154348L
Run Code Online (Sandbox Code Playgroud)

这里的 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,)
Run Code Online (Sandbox Code Playgroud)

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