Reputation: 47
How can I convert a number with a decimal part to the simple precision system of the IEEE-754 in python in such a way that I enter the number and I throw the standard sign, exponent and mantissa? Example Input: 10.27 Example Output: 0 10000011 01001000101000111101011 Sign-Exponent-Mantissa
Here is my attempt to solve the problem.
# Conversion de Decimal a Binario con parte fraccionaria
def float_bin(num, dig=23):
# split() separa la parte entera de la parte decimal
# Despues de separarlas las asignas a dos variables distintas
ent, dec = str(num).split(".")
# Convert both whole number and decimal
# Cambia el tipo de dato de un string a un entero
ent = int(ent)
dec = int(dec)
# Convierte la parte entera a su respectivo forma binaria el "Ob" es removido con el metodo strip
res = bin(ent).lstrip("0b") + "."
# Itera el numero de veces dependiendo de numero de posiciones decimales que se buscan
for x in range(dig):
# Multiplica la parte fraccionaria por 2 y se separa la parte entera de la parte decimal para repetir el proceso
ent, dec = str((decimal_conv(dec)) * 2).split(".")
# Se convierte la parte fraccionaria a un entero de nuevo
dec = int(dec)
# Keep adding the integer parts
# receive to the result variable
res += ent
return res
# Function converts the value passed as
# parameter to it's decimal representation
def decimal_conv(num10):
while num10 > 1:
num10 /= 10
return num10
# Take the user input for
# the floating point number
n = input("Ingrese su numero de punto flotante : \n")
# Take user input for the number of
# decimal places user want result as
p = int(input("Ingrese el numero de posiciones decimales para el resultado: \n"))
print(float_bin(n, dig=p))
while True:
ParteSigno = input("Ingresa el signo: ")
ParteEntera = list(input("Ingresa la parte entera: "))
ParteDecimal = list(input("Ingresa la parte decimal: "))
if (ParteSigno == '-'):
signo = 1
else:
signo = 0
Recorrido = []
Topepunto = 0
sacador = 0
saca = 0
cont = 0
if '1' in (ParteEntera):
Topepunto = len(ParteEntera) - 1
ExpPar = 127 + Topepunto
ExpBina = bin(ExpPar)
ExpobinList = []
mantisalncom = ParteEntera + ParteDecimal
mantisalncom.reverse()
parte = mantisalncom.pop()
mantisalncom.reverse()
while len(mantisalncom) < 23:
mantisalncom.extend("0")
for i in ExpBina:
ExpobinList.append(i) #El metodo append añade un elemento a la lista
ExpobinList = (ExpobinList[2:])
if len(ExpobinList) < 8:
ExpobinList.reverse()
while len(ExpobinList) <= 8:
ExpobinList.extend('0')
ExpobinList.reverse()
else:
mantisalncom = ParteEntera + ParteDecimal
ParteDecimal.reverse()
mantisalncom.reverse()
while cont == 0:
parte = mantisalncom.pop()
if parte == '0' and cont == 0:
cont = 0
elif parte == '1' and cont == 0:
cont = cont + 1
mantisalncom.reverse()
while len(mantisalncom) < 23:
mantisalncom.extend('0')
while len(ParteDecimal) > 0:
Reco = ParteDecimal.pop()
if (Reco == '0' and sacador == 0):
Recorrido.extend(Reco)
sacador = 0
else:
sacador = sacador + 1
Topepunto = len(Recorrido) + 1
Topepunto = Topepunto * (-1)
ExpPar = 127 + Topepunto
ExpBina = bin(ExpPar)
ExpobinList = []
for i in ExpBina:
ExpobinList.append(i)
ExpobinList = (ExpobinList[2:])
if len(ExpobinList) < 8:
ExpobinList.reverse()
while len(ExpobinList) < 8:
ExpobinList.extend('0')
ExpobinList.reverse()
print("\n\nSigno\t\tExponente\t\t\t\t\t\t\t\tMantisa\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t")
print("", signo, "", ExpobinList, mantisalncom)
Upvotes: 1
Views: 14984
Reputation: 176
What you want to do is use struct pack and unpack with !f
>f
or <f
.
This code works for 32 bit floating point numbers.
for reference look at: https://docs.python.org/3/library/struct.html
Character | Byte order | Size | Alignment |
---|---|---|---|
@ |
native | native | native |
= |
native | standard | none |
< |
little-endian | standard | none |
> |
big-endian | standard | none |
! |
network (big-endian) | standard | none |
For 64 bit floating point numbers use d
in stead of f
import struct
def from_bytes(b):
return struct.unpack('!f', b)[0]
def from_hex(h):
return from_bytes(bytes.fromhex(h))
def from_bin(b):
return struct.unpack('!f', int(b, 2).to_bytes(4, byteorder='big'))[0]
def to_bytes(f):
return struct.pack('!f', f)
def to_hex(f):
return to_bytes(f).hex()
def to_bin(f):
return '{:032b}'.format(struct.unpack('>I', struct.pack('!f', f))[0])
assert from_hex('c4725c44') == -969.441650390625
assert from_bin('11000100011100100101110001000100') == -969.441650390625
assert from_bytes(b'\xc4r\\D') == -969.441650390625
assert to_hex(-969.441650390625) == 'c4725c44'
assert to_bin(-969.441650390625) == '11000100011100100101110001000100'
assert to_bytes(-969.441650390625) == b'\xc4r\\D'
Upvotes: 0
Reputation: 692
Here is an example for ieee745 32b-format:
def ieee745(N): # ieee-745 bits (max 32 bit)
a = int(N[0]) # sign, 1 bit
b = int(N[1:9],2) # exponent, 8 bits
c = int("1"+N[9:], 2)# fraction, len(N)-9 bits
return (-1)**a * c /( 1<<( len(N)-9 - (b-127) ))
N = "110000011010010011" # str of ieee-745 bits
print( ieee745(N) ) # --> -20.59375
Upvotes: 4
Reputation: 42758
From your description ucyos answer is what you are looking for:
def float_to_bin(num):
bits, = struct.unpack('!I', struct.pack('!f', num))
return "{:032b}".format(bits)
print(float_to_bin(10.27))
# 01000001001001000101000111101100
Upvotes: 3