如何使用python将hex转换为signed long long?

时间:2017-12-19 10:37:58

标签: python signed

我有一个十六进制字符串f6befc34e3de2d30。我想将它转换为签名长,但

x['id'], = struct.unpack('>q', 'f6befc34e3de2d30'.decode('hex'))

给出:

-0b100101000001000000111100101100011100001000011101001011010000

0b1111011010111110111111000011010011100011110111100010110100110000

预期。

谢谢!

1 个答案:

答案 0 :(得分:3)

你可以long('f6befc34e3de2d30', 16)

bin(long('f6befc34e3de2d30', 16))
>>> '0b1111011010111110111111000011010011100011110111100010110100110000'

编辑:跟进@Paul Panzer的评论。对于基于ALU硬件的C类型长实现,情况确实如此。你不能有大于2 ^ 63的有符号整数。但是,Python的实现是不同的,并且依赖于大数字的数组表示,以及用于算术运算的Karatsuba算法。这就是为什么这种方法有效。

编辑2 :关注OP问题。没有“第一位作为标志”的问题。在您的问题中,您明确地希望使用Python的long构造,对于该构造,实现不是您期望的那种,它使用的表示与您在C中可能熟悉的表示不同。相反,它将大整数表示为数组。因此,如果您想实现某种第一位逻辑,则必须自己完成。我没有任何文化或经验,所以以下可能会因为有人知道他的东西而完全错误,但仍然让我给你我的看法。

我看到两种方法。在第一个中,您同意您想要使用的最大长度的约定,然后实现ALU所执行的相同类型的逻辑。让我们说,为了论证,我们希望在[-2^127, 2^127-1]范围内使用长符号。我们可以做以下

MAX_LONG = long('1' + "".join([str(0)]*127), 2)

def parse_nb(s):
    # returns the first bit and the significand in the case of a usual
    # integer representation
    b = bin(long(s, 16))
    if len(b) < 130:  # deal with the case where the leading zeros are absent
        return "0", b[2:]
    else:
        return b[2], b[3:]

def read_long(s):
    # takes an hexadecimal representation of a string, and return
    # the corresponding long with the convention stated above 
    sign, mant = parse_nb(s)
    b = "0b" + mant
    if sign == "0":
        return long(b, 2)
    else:
        return -MAX_LONG + long(b, 2)

read_long('5')
>>> 5L
# fffffffffffffffffffffffffffffffb is the representation of -5 using the
# usual integer representation, extended to 128 bits integers
read_long("fffffffffffffffffffffffffffffffb")
>>> -5L

对于第二种方法,您不认为存在MAX_LONG,而是第一位始终是符号位。然后你必须修改上面的parse_nb方法。我把它留作练习:)。