Двоичное представление float в Python (бит не hex)

Как получить строку как двоичное представление IEEE 754 из 32-битного поплавка?

пример

1.00 -> '00111111100000000000000000000000'

  • Почему tkinter отлично работает с многопроцессорной обработкой?
  • Scrapy - Реактор не восстанавливается
  • сделать всплывающее окно matplotlib в качестве активного
  • разбор URL-адреса в python с изменением его части
  • Извлечение текста между тегами с помощью BeautifulSoup
  • используя «OR» для выбора данных в пандах
  • Python / Pandas / Numpy - прямой расчет количества рабочих дней между двумя датами, исключая праздники
  • Создание необработанного HTTP-запроса с сокетами
  • 9 Solutions collect form web for “Двоичное представление float в Python (бит не hex)”

    Вы можете сделать это с помощью пакета struct :

     import struct def binary(num): return ''.join(bin(ord(c)).replace('0b', '').rjust(8, '0') for c in struct.pack('!f', num)) 

    Это упаковывает его как сетевое байтовое упорядоченное float, а затем преобразует каждый из полученных байтов в 8-битное двоичное представление и объединяет их:

     >>> binary(1) '00111111100000000000000000000000' 

    Изменить : возникла просьба расширить объяснение. Я буду расширять это, используя промежуточные переменные, чтобы прокомментировать каждый шаг.

     def binary(num): # Struct can provide us with the float packed into bytes. The '!' ensures that # it's in network byte order (big-endian) and the 'f' says that it should be # packed as a float. Alternatively, for double-precision, you could use 'd'. packed = struct.pack('!f', num) print 'Packed: %s' % repr(packed) # For each character in the returned string, we'll turn it into its corresponding # integer code point # # [62, 163, 215, 10] = [ord(c) for c in '>\xa3\xd7\n'] integers = [ord(c) for c in packed] print 'Integers: %s' % integers # For each integer, we'll convert it to its binary representation. binaries = [bin(i) for i in integers] print 'Binaries: %s' % binaries # Now strip off the '0b' from each of these stripped_binaries = [s.replace('0b', '') for s in binaries] print 'Stripped: %s' % stripped_binaries # Pad each byte's binary representation's with 0's to make sure it has all 8 bits: # # ['00111110', '10100011', '11010111', '00001010'] padded = [s.rjust(8, '0') for s in stripped_binaries] print 'Padded: %s' % padded # At this point, we have each of the bytes for the network byte ordered float # in an array as binary strings. Now we just concatenate them to get the total # representation of the float: return ''.join(padded) 

    И результат для нескольких примеров:

     >>> binary(1) Packed: '?\x80\x00\x00' Integers: [63, 128, 0, 0] Binaries: ['0b111111', '0b10000000', '0b0', '0b0'] Stripped: ['111111', '10000000', '0', '0'] Padded: ['00111111', '10000000', '00000000', '00000000'] '00111111100000000000000000000000' >>> binary(0.32) Packed: '>\xa3\xd7\n' Integers: [62, 163, 215, 10] Binaries: ['0b111110', '0b10100011', '0b11010111', '0b1010'] Stripped: ['111110', '10100011', '11010111', '1010'] Padded: ['00111110', '10100011', '11010111', '00001010'] '00111110101000111101011100001010' 

    Вот уродливый …

     >>> import struct >>> bin(struct.unpack('!i',struct.pack('!f',1.0))[0]) '0b111111100000000000000000000000' 

    В принципе, я просто использовал структурный модуль для преобразования float в int …


    Вот немного лучше, используя ctypes :

     >>> import ctypes >>> bin(ctypes.c_uint.from_buffer(ctypes.c_float(1.0)).value) '0b111111100000000000000000000000' 

    В принципе, я c_uint float и использую ту же ячейку памяти, но я c_uint ее как c_uint . Значение c_uint – это целое число python, на которое вы можете использовать встроенную функцию bin .

    Нашел другое решение, используя модуль bitstring .

     import bitstring f1 = bitstring.BitArray(float=1.0, length=32) print f1.read('bin') 

    Вывод:

     00111111100000000000000000000000 

    Эта проблема более тщательно обрабатывается, разбивая ее на две части.

    Первый заключается в преобразовании float в int с эквивалентным битовым шаблоном:

     def float32_bit_pattern(value): return sum(ord(b) << 8*i for i,b in enumerate(struct.pack('f', value))) 

    Затем преобразуем int в строку:

     def int_to_binary(value, bits): return bin(value).replace('0b', '').rjust(bits, '0') 

    Теперь объедините их:

     >>> int_to_binary(float32_bit_pattern(1.0), 32) '00111111100000000000000000000000' 

    Для полноты вы можете добиться этого с помощью numpy, используя:

     f = 1.00 int32bits = np.asarray(f, dtype=np.float32).view(np.int32).item() # item() optional 

    Затем вы можете распечатать это с помощью дополнения, используя спецификатор формата b

     print('{:032b}'.format(int32bits)) 

    После просмотра многих подобных вопросов я написал что-то, что, надеюсь, сделает то, что я хотел.

     f = 1.00 negative = False if f < 0: f = f*-1 negative = True s = struct.pack('>f', f) p = struct.unpack('>l', s)[0] hex_data = hex(p) scale = 16 num_of_bits = 32 binrep = bin(int(hex_data, scale))[2:].zfill(num_of_bits) if negative: binrep = '1' + binrep[1:] 

    binrep . Каждая часть будет объяснена.


     f = 1.00 negative = False if f < 0: f = f*-1 negative = True 

    Преобразует число в положительное, если отрицательное, и устанавливает переменную отрицательную в значение false. Причина этого заключается в том, что разница между положительными и отрицательными двоичными представлениями находится только в первом бите, и это был более простой способ, чем выяснить, что пойдет не так, когда вы делаете весь процесс с отрицательными числами.


     s = struct.pack('>f', f) #'?\x80\x00\x00' p = struct.unpack('>l', s)[0] #1065353216 hex_data = hex(p) #'0x3f800000' 

    s – шестнадцатеричное представление двоичного f . это, однако, не в симпатичной форме, в которой я нуждаюсь. То, где p входит. Это int-представление шестнадцатеричных s. И затем другое преобразование, чтобы получить красивый гекс.


     scale = 16 num_of_bits = 32 binrep = bin(int(hex_data, scale))[2:].zfill(num_of_bits) if negative: binrep = '1' + binrep[1:] 

    scale – это основание 16 для шестнадцатеричного. num_of_bits равно 32, поскольку float 32 бита, он используется позже, чтобы заполнить дополнительные места 0, чтобы добраться до 32. Получил код для binrep из этого вопроса . Если число было отрицательным, просто измените первый бит.


    Я знаю, что это уродливо, но я не нашел приятного пути, и мне это было нужно быстро. Комментарии приветствуются.

    Вы можете использовать .format для легкого представления бит на мой взгляд:

    мой код будет выглядеть примерно так:

     def fto32b(flt): # is given a 32 bit float value and converts it to a binary string if isinstance(flt,float): # THE FOLLOWING IS AN EXPANDED REPRESENTATION OF THE ONE LINE RETURN # packed = struct.pack('!f',flt) <- get the hex representation in (!)Big Endian format of a (f) Float # integers = [] # for c in packed: # integers.append(ord(c)) <- change each entry into an int # binaries = [] # for i in integers: # binaries.append("{0:08b}".format(i)) <- get the 8bit binary representation of each int (00100101) # binarystring = ''.join(binaries) <- join all the bytes together # return binarystring return ''.join(["{0:08b}".format(i) for i in [ord(c) for c in struct.pack('!f',flt)]]) return None 

    Вывод:

     >>> a = 5.0 '01000000101000000000000000000000' >>> b = 1.0 '00111111100000000000000000000000' 

    Некоторые из этих ответов не работали так, как написано с Python 3, или не дали правильного представления для отрицательных чисел с плавающей запятой. Я нашел следующее для работы для меня (хотя это дает 64-битное представление, которое мне нужно)

     def float_to_binary_string(f): def int_to_8bit_binary_string(n): stg=bin(n).replace('0b','') fillstg = '0'*(8-len(stg)) return fillstg+stg return ''.join( int_to_8bit_binary_string(int(b)) for b in struct.pack('>d',f) ) 

    Это немного больше, чем было задано, но это было то, что мне было нужно, когда я нашел эту запись. Этот код предоставит мантиссе, базу и знак 32-битного поплавка IEEE 754.

     import ctypes def binRep(num): binNum = bin(ctypes.c_uint.from_buffer(ctypes.c_float(num)).value)[2:] print("bits: " + binNum.rjust(32,"0")) mantissa = "1" + binNum[-23:] print("sig (bin): " + mantissa.rjust(24)) mantInt = int(mantissa,2)/2**23 print("sig (float): " + str(mantInt)) base = int(binNum[-31:-23],2)-127 print("base:" + str(base)) sign = 1-2*("1"==binNum[-32:-31].rjust(1,"0")) print("sign:" + str(sign)) print("recreate:" + str(sign*mantInt*(2**base))) binRep(-0.75) 

    вывод:

     bits: 10111111010000000000000000000000 sig (bin): 110000000000000000000000 sig (float): 1.5 base:-1 sign:-1 recreate:-0.75 
    Python - лучший язык программирования в мире.