87 votes

Représentation binaire d'un float en Python (bits non hex)

Comment obtenir la chaîne sous forme de représentation binaire IEEE 754 d'un flottant 32 bits ?

Exemple

1.00 -> '00111111100000000000000000000000'

9voto

JavDomGom Points 41

Avec ces deux fonctions simples ( Python >=3.6 ) vous pouvez facilement convertir un nombre flottant en binaire et vice versa, pour IEEE 754 binaire64.

import struct

def bin2float(b):
    ''' Convert binary string to a float.

    Attributes:
        :b: Binary string to transform.
    '''
    h = int(b, 2).to_bytes(8, byteorder="big")
    return struct.unpack('>d', h)[0]

def float2bin(f):
    ''' Convert float to 64-bit binary string.

    Attributes:
        :f: Float number to transform.
    '''
    [d] = struct.unpack(">Q", struct.pack(">d", f))
    return f'{d:064b}'

Par exemple :

print(float2bin(1.618033988749894))
print(float2bin(3.14159265359))
print(float2bin(5.125))
print(float2bin(13.80))

print(bin2float('0011111111111001111000110111011110011011100101111111010010100100'))
print(bin2float('0100000000001001001000011111101101010100010001000010111011101010'))
print(bin2float('0100000000010100100000000000000000000000000000000000000000000000'))
print(bin2float('0100000000101011100110011001100110011001100110011001100110011010'))

La sortie est :

0011111111111001111000110111011110011011100101111111010010100100
0100000000001001001000011111101101010100010001000010111011101010
0100000000010100100000000000000000000000000000000000000000000000
0100000000101011100110011001100110011001100110011001100110011010
1.618033988749894
3.14159265359
5.125
13.8

J'espère que vous l'apprécierez, il fonctionne parfaitement pour moi.

5voto

La réponse de Dan est suivie d'une version colorée pour Python3 :

import struct

BLUE = "\033[1;34m"
CYAN = "\033[1;36m"
GREEN = "\033[0;32m"
RESET = "\033[0;0m"

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

def binary_str(num):
    bits = ''.join(binary(num))
    return ''.join([BLUE, bits[:1], GREEN, bits[1:10], CYAN, bits[10:], RESET])

def binary_str_fp16(num):
    bits = ''.join(binary(num))
    return ''.join([BLUE, bits[:1], GREEN, bits[1:10][-5:], CYAN, bits[10:][:11], RESET])

x = 0.7
print(x, "as fp32:", binary_str(0.7), "as fp16 is sort of:", binary_str_fp16(0.7))

colored representation

2voto

Alan Points 1636

Après avoir parcouru de nombreuses questions similaires, j'ai rédigé un texte qui, je l'espère, répond à mes attentes.

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 est le résultat. Chaque partie sera expliquée.


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

Convertit le nombre en positif s'il est négatif, et définit la variable négative à false. La raison en est que la différence entre les représentations binaires positives et négatives se trouve juste dans le premier bit, et c'était la manière la plus simple de comprendre ce qui ne va pas quand on fait tout le processus avec des nombres négatifs.


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

s est une représentation hexagonale du code binaire f Cependant, elle n'est pas sous la jolie forme dont j'ai besoin. C'est là que P entre en jeu. C'est la représentation int de l'hex s. Et ensuite une autre conversion pour obtenir un joli hex.


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

scale est la base 16 de l'hexagone. num_of_bits est 32, comme le float est de 32 bits, il est utilisé plus tard pour remplir les places supplémentaires avec 0 pour arriver à 32. J'ai obtenu le code pour binrep de cette question . Si le nombre était négatif, il suffit de changer le premier bit.


Je sais que c'est moche, mais je n'ai pas trouvé de moyen agréable et j'en avais besoin rapidement. Les commentaires sont les bienvenus.

2voto

johnml1135 Points 1010

C'est un peu plus que ce qui était demandé, mais c'est ce dont j'avais besoin lorsque j'ai trouvé cet article. Ce code donnera la mantisse, la base et le signe d'un flottant 32 bits 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)

sortie :

bits: 10111111010000000000000000000000
sig (bin): 110000000000000000000000
sig (float): 1.5
base:-1
sign:-1
recreate:-0.75

1voto

tttzof351 Points 11

Convertir un flottant entre 0..1

def float_bin(n, places = 3): 
    if (n < 0 or n > 1):
        return "ERROR, n must be in 0..1"

    answer = "0."
    while n > 0:
        if len(answer) - 2 == places: 
            return answer

        b = n * 2
        if b >= 1:
            answer += '1'
            n = b - 1
        else:
            answer += '0'
            n = b

    return answer

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X