在 Python 中将十六进制解压为双精度

发布于 2024-09-15 15:35:37 字数 269 浏览 5 评论 0原文

Python:从十六进制解包到双精度

value = ['\x7f', '\x15', '\xb7', '\xdb', '5', '\x03', '\xc0', '@']

这是我尝试过的

unpack('d', value)

,但他需要一个字符串来解包。现在是一个列表。但是当我将其更改为字符串时,长度将从 8 更改为 58。但是 double 需要长度为 8 的值。

Python: Unpack from hex to double

This is the value

value = ['\x7f', '\x15', '\xb7', '\xdb', '5', '\x03', '\xc0', '@']

I tried

unpack('d', value)

but he needs a string for unpacking. It is a list now. But when I change it to a string, the length will change from 8 to 58. But a double needs a value of the length 8.

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

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

发布评论

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

评论(4

往事风中埋 2024-09-22 15:35:37

使用 ''.join join 进行转换列表到字符串:

>>> value = ['\x7f', '\x15', '\xb7', '\xdb', '5', '\x03', '\xc0', '@']
>>> ''.join(value)
'\x7f\x15\xb7\xdb5\x03\xc0@'
>>> from struct import unpack
>>> unpack('d', ''.join(value))
(8198.4207676749193,)

Use ''.join join to convert the list to a string:

>>> value = ['\x7f', '\x15', '\xb7', '\xdb', '5', '\x03', '\xc0', '@']
>>> ''.join(value)
'\x7f\x15\xb7\xdb5\x03\xc0@'
>>> from struct import unpack
>>> unpack('d', ''.join(value))
(8198.4207676749193,)
空心空情空意 2024-09-22 15:35:37

请注意,有两种方法可以将其转换为双精度数,具体取决于 cpu 是否为大尾数法或小尾数法,因此最好明确您想要哪一种,

>>> from struct import unpack
>>> value = ['\x7f', '\x15', '\xb7', '\xdb', '5', '\x03', '\xc0', '@']
>>> unpack('<d', ''.join(value))[0]
8198.42076767492
>>> unpack('>d', ''.join(value))[0]
1.4893584640656973e+304

并且只是为了好玩 - 以下是如何显式解码双精度数

>>> value = ['\x7f', '\x15', '\xb7', '\xdb', '5', '\x03', '\xc0', '@']
>>> bytes = map(ord,reversed(value))
>>> sign = (1,-1)[bytes[0]>>7]
>>> exp = ((0x7f&bytes[0])<<4) + (bytes[1]>>4) - 1023
>>> mantissa = reduce(lambda x,y: (x<<8) + y, bytes[2:], bytes[1]&0xf)
>>> sign*2**exp*(1+mantissa*2**-52)
8198.4207676749193

Note that there are two ways to convert this to a double, depending on whether the cpu is bigendian oe littleendian, so it's best to be explicit about which one you want

>>> from struct import unpack
>>> value = ['\x7f', '\x15', '\xb7', '\xdb', '5', '\x03', '\xc0', '@']
>>> unpack('<d', ''.join(value))[0]
8198.42076767492
>>> unpack('>d', ''.join(value))[0]
1.4893584640656973e+304

and just for fun - here's how to decode the double explicitly

>>> value = ['\x7f', '\x15', '\xb7', '\xdb', '5', '\x03', '\xc0', '@']
>>> bytes = map(ord,reversed(value))
>>> sign = (1,-1)[bytes[0]>>7]
>>> exp = ((0x7f&bytes[0])<<4) + (bytes[1]>>4) - 1023
>>> mantissa = reduce(lambda x,y: (x<<8) + y, bytes[2:], bytes[1]&0xf)
>>> sign*2**exp*(1+mantissa*2**-52)
8198.4207676749193
森林很绿却致人迷途 2024-09-22 15:35:37

注意在实现之前验证值,使用以下函数转换 HEX->Double 或 Double->HEX。

>>> import struct
>>> def double_to_hex(f):
    return hex(struct.unpack('<Q', struct.pack('<d', f))[0])

>>> def hex_to_double(f):
    return struct.unpack('!d', bytes.fromhex(f))[0]

>>> data = 12.982947
>>> hex_value = double_to_hex(data)
>>> print(hex_value)
0x4029f744d4456712
>>> double_value = hex_to_double(hex_value[2:])
>>> print(double_value)
12.982947

Note verify the value before implementation use below functions to convert HEX->Double or Double->HEX.

>>> import struct
>>> def double_to_hex(f):
    return hex(struct.unpack('<Q', struct.pack('<d', f))[0])

>>> def hex_to_double(f):
    return struct.unpack('!d', bytes.fromhex(f))[0]

>>> data = 12.982947
>>> hex_value = double_to_hex(data)
>>> print(hex_value)
0x4029f744d4456712
>>> double_value = hex_to_double(hex_value[2:])
>>> print(double_value)
12.982947
雪化雨蝶 2024-09-22 15:35:37

您还可以使用ctypes 库进行此转换。

from ctypes import pointer, cast, POINTER, c_double, c_longlong

def convert_longlong_to_double(s):
    try:
        i = int(s, 10)                   # convert from hex to a Python int
    except Exception:
        i = s
    cp = pointer(c_longlong(i))           # make this into a c long long
    fp = cast(cp, POINTER(c_double))  # cast the long long pointer to a double pointer
    return fp.contents.value         # dereference the pointer, get the double

用法示例:

r1 = 0
r2 = 0
r3 = 16473
r4 = 0

longlong = (r1 << 16) | (r2 << 0) | (r3 << 48) | (r4 << 32)
print(convert_longlong_to_double(longlong))

You can also use ctypes library for this conversion.

from ctypes import pointer, cast, POINTER, c_double, c_longlong

def convert_longlong_to_double(s):
    try:
        i = int(s, 10)                   # convert from hex to a Python int
    except Exception:
        i = s
    cp = pointer(c_longlong(i))           # make this into a c long long
    fp = cast(cp, POINTER(c_double))  # cast the long long pointer to a double pointer
    return fp.contents.value         # dereference the pointer, get the double

Example usage:

r1 = 0
r2 = 0
r3 = 16473
r4 = 0

longlong = (r1 << 16) | (r2 << 0) | (r3 << 48) | (r4 << 32)
print(convert_longlong_to_double(longlong))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文