Преобразуйте шестнадцатеричное число для плавания

@"{search}" FTW.

Возврат, что заголовок и это волшебно заменяются корректным глифом.

35
задан mskfisher 10 May 2012 в 18:50
поделиться

4 ответа

>>> import struct
>>> struct.unpack('!f', '41973333'.decode('hex'))[0]
18.899999618530273
>>> struct.unpack('!f', '41995C29'.decode('hex'))[0]
19.170000076293945
>>> struct.unpack('!f', '470FC614'.decode('hex'))[0]
36806.078125

Обновление: см. Комментарий о том, как это сделать в Python 3.

56
ответ дан 27 November 2019 в 06:52
поделиться

Я рекомендую использовать модуль ctypes , который в основном позволяет вам работать с типами данных низкого уровня. В вашем случае вы могли бы сказать

from ctypes import *

def convert(s):
    i = int(s, 16)                   # convert from hex to a Python int
    cp = pointer(c_int(i))           # make this into a c integer
    fp = cast(cp, POINTER(c_float))  # cast the int pointer to a float pointer
    return fp.contents.value         # dereference the pointer, get the float

print convert("41973333")    # returns 1.88999996185302734375E1

print convert("41995C29")    # returns 1.91700000762939453125E1

print convert("470FC614")    # returns 3.6806078125E4

Я считаю, что модуль ctypes имеет здесь смысл, потому что вы, по сути, спрашиваете, как выполнить низкоуровневое преобразование битов. Ваш вопрос в основном заключается в том, как мне сказать Python взять некоторые данные и интерпретировать эти данные, как если бы те же самые биты были другим типом данных?

В C, если у вас есть int и вы хотите интерпретировать его биты как float, вы бы сделали примерно то же самое, взяв указатель, а затем преобразовав его и разыменовав:

int i = 0x41973333;
float f = *((float*)&i);

и это именно то, что делает код Python, использующий библиотеку ctypes в моем примере.

13
ответ дан 27 November 2019 в 06:52
поделиться

Я предполагаю, что этот вопрос относится к этому , и вы работаете с 4 байтами, а не с 8 шестнадцатеричными цифрами.

"\ x41 \ x91 \ x33 \ x33" - это 4-байтовая строка, хотя она выглядит как 16

>>> len("\x41\x91\x33\x33")
4
>>> import struct  
>>> struct.unpack(">fff","\x41\x97\x33\x33\x41\x99\x5C\x29\x47\x0F\xC6\x14")
(18.899999618530273, 19.170000076293945, 36806.078125)

Если вам действительно нужно иметь дело со строкой шестнадцатеричных цифр, а не с фактическими байтами, вы можете использовать struct.pack для ее преобразования, вот так

>>> for hx in ["41973333","41995C29","470FC614"]:
...     print(struct.unpack(">f",struct.pack(">i",int(hx,16)))[0])
... 
18.8999996185
19.1700000763
36806.078125
5
ответ дан 27 November 2019 в 06:52
поделиться

Разделите шестнадцатеричные строки на двухсимвольные фрагменты (байты), превратите каждый фрагмент в правый байт с форматированием int, по завершении - struct.unpack. То есть:

import struct 

testcases = {
"41973333": 1.88999996185302734375E1,
"41995C29": 1.91700000762939453125E1,
"470FC614": 3.6806078125E4,
}

def hex2float(s):
    bins = ''.join(chr(int(s[x:x+2], 16)) for x in range(0, len(s), 2))
    return struct.unpack('>f', bins)[0]

for s in testcases:
  print hex2float(s), testcases[s]

излучающий, как желательно:

18.8999996185 18.8999996185
19.1700000763 19.1700000763
36806.078125 36806.078125
4
ответ дан 27 November 2019 в 06:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: