Python 中十六进制字符串到有符号 int

发布于 2024-11-25 03:54:43 字数 433 浏览 0 评论 0原文

如何在 Python 3 中将十六进制字符串转换为有符号整型?

我能想到的最好的办法

h = '9DA92DAB'
b = bytes(h, 'utf-8')
ba = binascii.a2b_hex(b)
print(int.from_bytes(ba, byteorder='big', signed=True))

是有更简单的方法吗?无符号更容易: int(h, 16)

顺便说一句,问题的起源是 itunes 持久 id - 音乐库 xml 版本和 iTunes 十六进制版本

How do I convert a hex string to a signed int in Python 3?

The best I can come up with is

h = '9DA92DAB'
b = bytes(h, 'utf-8')
ba = binascii.a2b_hex(b)
print(int.from_bytes(ba, byteorder='big', signed=True))

Is there a simpler way? Unsigned is so much easier: int(h, 16)

BTW, the origin of the question is itunes persistent id - music library xml version and iTunes hex version

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

往日情怀 2024-12-02 03:54:43

在 n 位二进制补码中,位具有值:

位 0 = 20
位 1 = 21
位 n-2 = 2n-2
位 n-1 = -2n-1

但位 n-1 在无符号时值为 2n-1,因此数字为 2n > 太高。如果设置了位 n-1,则减去 2n

def twos_complement(hexstr, bits):
    value = int(hexstr, 16)
    if value & (1 << (bits - 1)):
        value -= 1 << bits
    return value

print(twos_complement('FFFE', 16))
print(twos_complement('7FFF', 16))
print(twos_complement('7F', 8))
print(twos_complement('FF', 8))

输出:

-2
32767
127
-1

In n-bit two's complement, bits have value:

bit 0 = 20
bit 1 = 21
bit n-2 = 2n-2
bit n-1 = -2n-1

But bit n-1 has value 2n-1 when unsigned, so the number is 2n too high. Subtract 2n if bit n-1 is set:

def twos_complement(hexstr, bits):
    value = int(hexstr, 16)
    if value & (1 << (bits - 1)):
        value -= 1 << bits
    return value

print(twos_complement('FFFE', 16))
print(twos_complement('7FFF', 16))
print(twos_complement('7F', 8))
print(twos_complement('FF', 8))

Output:

-2
32767
127
-1
九命猫 2024-12-02 03:54:43
import struct

对于Python 3(带有注释的帮助):

h = '9DA92DAB'
struct.unpack('>i', bytes.fromhex(h))

对于Python 2:

h = '9DA92DAB'
struct.unpack('>i', h.decode('hex'))

或者如果它是小端:

h = '9DA92DAB'
struct.unpack('<i', h.decode('hex'))
import struct

For Python 3 (with comments' help):

h = '9DA92DAB'
struct.unpack('>i', bytes.fromhex(h))

For Python 2:

h = '9DA92DAB'
struct.unpack('>i', h.decode('hex'))

or if it is little endian:

h = '9DA92DAB'
struct.unpack('<i', h.decode('hex'))
糖果控 2024-12-02 03:54:43

这是一个可用于任何大小的十六进制的通用函数:

import math

# hex string to signed integer
def htosi(val):
    uintval = int(val,16)
    bits = 4 * (len(val) - 2)
    if uintval >= math.pow(2,bits-1):
        uintval = int(0 - (math.pow(2,bits) - uintval))
    return uintval

并使用它:

h = str(hex(-5))
h2 = str(hex(-13589))
x = htosi(h)
x2 = htosi(h2)

Here's a general function you can use for hex of any size:

import math

# hex string to signed integer
def htosi(val):
    uintval = int(val,16)
    bits = 4 * (len(val) - 2)
    if uintval >= math.pow(2,bits-1):
        uintval = int(0 - (math.pow(2,bits) - uintval))
    return uintval

And to use it:

h = str(hex(-5))
h2 = str(hex(-13589))
x = htosi(h)
x2 = htosi(h2)
誰認得朕 2024-12-02 03:54:43

这适用于 16 位有符号整数,您可以扩展为 32 位整数。它使用 2 的补码有符号数的基本定义。 另请注意,与 1 的异或是与二进制否定相同。

# convert to unsigned
x = int('ffbf', 16) # example (-65)
# check sign bit
if (x & 0x8000) == 0x8000:
    # if set, invert and add one to get the negative value, then add the negative sign
    x = -( (x ^ 0xffff) + 1)

This works for 16 bit signed ints, you can extend for 32 bit ints. It uses the basic definition of 2's complement signed numbers. Also note xor with 1 is the same as a binary negate.

# convert to unsigned
x = int('ffbf', 16) # example (-65)
# check sign bit
if (x & 0x8000) == 0x8000:
    # if set, invert and add one to get the negative value, then add the negative sign
    x = -( (x ^ 0xffff) + 1)
上课铃就是安魂曲 2024-12-02 03:54:43

这是一个很晚的答案,但这里有一个执行上述操作的函数。这将延伸到您提供的任何长度。将此部分归功于另一个 SO 答案(我丢失了链接,所以如果您找到它,请提供它)。

def hex_to_signed(source):
    """Convert a string hex value to a signed hexidecimal value.

    This assumes that source is the proper length, and the sign bit
    is the first bit in the first byte of the correct length.

    hex_to_signed("F") should return -1.
    hex_to_signed("0F") should return 15.
    """
    if not isinstance(source, str):
        raise ValueError("string type required")
    if 0 == len(source):
        raise valueError("string is empty")
    sign_bit_mask = 1 << (len(source)*4-1)
    other_bits_mask = sign_bit_mask - 1
    value = int(source, 16)
    return -(value & sign_bit_mask) | (value & other_bits_mask)

It's a very late answer, but here's a function to do the above. This will extend for whatever length you provide. Credit for portions of this to another SO answer (I lost the link, so please provide it if you find it).

def hex_to_signed(source):
    """Convert a string hex value to a signed hexidecimal value.

    This assumes that source is the proper length, and the sign bit
    is the first bit in the first byte of the correct length.

    hex_to_signed("F") should return -1.
    hex_to_signed("0F") should return 15.
    """
    if not isinstance(source, str):
        raise ValueError("string type required")
    if 0 == len(source):
        raise valueError("string is empty")
    sign_bit_mask = 1 << (len(source)*4-1)
    other_bits_mask = sign_bit_mask - 1
    value = int(source, 16)
    return -(value & sign_bit_mask) | (value & other_bits_mask)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文