0

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)
Rory Daulton
  • 21,934
  • 6
  • 42
  • 50
Osmar HD
  • 37
  • 1
  • 1
  • 6
  • 2
    Please include some example input and your expected output. – wim Jul 04 '18 at 18:16
  • do you mean [single precision](https://www.wiki-zero.co/index.php?q=aHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvU2luZ2xlLXByZWNpc2lvbl9mbG9hdGluZy1wb2ludF9mb3JtYXQ0); and by *throw* you want to omit? – vahdet Jul 04 '18 at 18:18
  • My attempt to solve the problem is the following code: https://pastebin.com/5a91ihgD – Osmar HD Jul 04 '18 at 18:23
  • You may find [this answer](https://stackoverflow.com/a/8762541/355230) of mine helpful. – martineau Jul 04 '18 at 18:24
  • I just updated the post – Osmar HD Jul 04 '18 at 18:24
  • Thanks but I'm looking for simple precision and that's double precision(64 bits) – Osmar HD Jul 04 '18 at 18:26
  • Do you mean *single* precision, as in four bytes, 32 bits? Also, do you want your task to be done the long way, or could the value just be stored in a single-precision variable then converted to binary in text? Could a module, such as numpy, be used? – Rory Daulton Jul 04 '18 at 18:28
  • martineau's answer seems to be the appropriate answer to this question. Adapting that code to 32 bits should be relatively trivial. – Silvio Mayolo Jul 04 '18 at 18:32
  • When I say simple precision I mean I'm using a total of 32 bits in the binary number 1 for the sign 8 for the exponent and 23 for the mantissa and i want de long way I already tried numpy but I did not find a similar module – Osmar HD Jul 04 '18 at 18:36
  • Silvio's how can I adapt the code for 32 bits? – Osmar HD Jul 04 '18 at 18:37
  • Related: [how to convert a float into binary using struct.unpack?](https://stackoverflow.com/q/46410429/674039) – wim Jul 04 '18 at 18:42

3 Answers3

3

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
Daniel
  • 42,087
  • 4
  • 55
  • 81
2

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
nino_701
  • 672
  • 3
  • 13
0

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'
Maximilian
  • 76
  • 5