Как преобразовать float в hex

В Python мне нужно преобразовать кучу поплавков в шестнадцатеричный. Он должен быть заполнен нулями (например, 0x00000010 вместо 0x10). Так же, как http://gregstoll.dyndns.org/~gregstoll/floattohex/. (к сожалению, я не могу использовать внешние библиотеки на своей платформе, поэтому я не могу использовать тот, который представлен на этом веб-сайте)

Каков наиболее эффективный способ сделать это?

Ответ 1

Это немного сложно в python, потому что они не хотят преобразовывать значение с плавающей запятой в целое число (hex). Вместо этого вы пытаетесь интерпретировать двоичное представление IEEE 754 значения с плавающей запятой как hex.

Мы будем использовать функции pack и unpack из встроенной библиотеки struct.

A float - 32 бит. Сначала мы скроем pack в двоичную строку 1 а затем unpack в качестве int.

def float_to_hex(f):
    return hex(struct.unpack('<I', struct.pack('<f', f))[0])

float_to_hex(17.5)    # Output: '0x418c0000'

Мы можем сделать то же самое для double, зная, что это 64 бита:

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

double_to_hex(17.5)   # Output: '0x4031800000000000L'

1 - значение строки необработанных байтов; не строка из них и нули.

Ответ 2

В Python float всегда выполняется двойная точность.

Если вам требуется, чтобы ваш ответ выводился в виде шестнадцатеричного целого числа, вопрос уже был отвечен:

import struct

# define double_to_hex as in the other answer

double_to_hex(17.5)   # Output: '0x4031800000000000'
double_to_hex(-17.5)  # Output: '0xc031800000000000'

Однако вместо этого вы можете использовать встроенную функцию:

(17.5).hex()    # Output: '0x1.1800000000000p+4'
(-17.5).hex()   # Output: '-0x1.1800000000000p+4'

# 0x1.18p+4 == (1 + 1./0x10 + 8./0x100) * 2**4 == 1.09375 * 16 == 17.5

Это тот же ответ, что и раньше, только в более структурированном и удобочитаемом формате.

Нижние 52 бита - мантисса. Верхние 12 бит состоят из знакового бита и 11-битного показателя; смещение экспоненты составляет 1023 == 0x3FF, поэтому 0x403 означает "4". См. Статья в Википедии о плавающей запятой IEEE.

Ответ 3

В дополнение к очень полезному ответу Джонатона Рейнхарта. Мне нужно было это, чтобы отправить число с плавающей запятой в байтах по UDP

import struct

# define double_to_hex (or float_to_hex)
def double_to_hex(f):
    return hex(struct.unpack('<Q', struct.pack('<d', f))[0])

# On the UDP transmission side
doubleAsHex = double_to_hex(17.5)
doubleAsBytes = bytearray.fromhex(doubleAsHex.lstrip('0x').rstrip('L'))

# On the UDP receiving side
doubleFromBytes = struct.unpack('>d', doubleAsBytes)[0] # or '>f' for float_to_hex

Ответ 4

если вы находитесь на микропитоне (который не указан в вопросе, но у меня возникли проблемы с поиском), вы можете использовать это

import binascii
def float_to_hex(f):
    binascii.hexlify(struct.pack('<f', f))

float_to_hex(17.5) #Answer: 0x418c0000