【问题标题】:Two's complement of Hex number in PythonPython中十六进制数的二进制补码
【发布时间】:2014-12-25 19:48:14
【问题描述】:

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

a = 0x17c7cc6e
b = 0xc158a854

现在我想知道以 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

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

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

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

【问题讨论】:

    标签: python python-2.7 binary hex


    【解决方案1】:
    >>> import numpy
    >>> numpy.int32(0xc158a854)
    -1051154348
    

    【讨论】:

    • 我收到OverflowError: Python int too large to convert to C long
    【解决方案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 已切换到将值处理为 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 的单行。
    【解决方案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'
    

    【讨论】:

      【解决方案4】:

      2^31 = 0x80000000(符号位,二进制补码表示-2^31)
      2^31-1 = 0x7fffffff(所有正位)

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

      你甚至可以用 n - ((n & 0x80000000)

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

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

      【讨论】:

        【解决方案5】:

        为什么不使用ctypes

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

        【讨论】:

          【解决方案6】:
          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}')
          

          【讨论】:

            猜你喜欢
            • 2016-05-24
            • 1970-01-01
            • 2012-11-02
            • 2014-04-16
            • 1970-01-01
            • 1970-01-01
            • 2014-11-03
            • 2014-03-01
            • 1970-01-01
            相关资源
            最近更新 更多