En este post de programación en Python te mostraré cómo convertir un número decimal en base 10 con parte fraccionaria a cualquier otra base; para el ejemplo te mostraré cómo convertir a la base 2 (binario), base 8 (octal) y base 16 (hexadecimal).
La diferencia con otros posts que te he mostrado es que ahora vamos a soportar números con punto decimal, parte fraccionaria o como le llames, y no solo números enteros.
Por ejemplo, podremos convertir el número decimal 3722.24
a E8A.3D70
en hexadecimal, usando Python.
Debemos separar la parte entera y decimal, algo que podemos hacer con modf
en Python. Luego debemos seguir el procedimiento que hacemos manualmente:
En el caso de la parte entera vamos dividiéndola entre la base y usando el residuo para saber cuál digito irá en el resultado.
Para la parte decimal o fraccionaria, vamos a ir multiplicando el valor decimal por la base, usar la parte entera del resultado como dígito para el resultado, y asignando la parte decimal a la parte fraccionaria original.
Todo esto que te explico está mejor explicado en el post del mismo tema pero en lenguaje C; te invito a darle un vistazo.
He encerrado el comportamiento de la conversión en una función de Python. Esto nos va a servir para convertir cualquier decimal con punto decimal a binario, octal y hexadecimal.
Ya te lo dije varias veces pero te lo repito: gracias a esto podremos convertir también la parte fraccionaria. Aquí el código:
import math
"""
Convertir el decimal con parte fraccionaria a cualquier base
decimal: el número decimal que se desea convertir. Por ejemplo, 12.34
base: la base a la que se desea convertir, si es binario es 2, octal 8, hexadecimal 16
digitos: los dígitos que componen a la base. Si es binario es "01", si es octal es "01234567", etcétera
https://parzibyte.me/blog
"""
def decimal_a_cualquier_base(decimal, base, digitos):
parte_fraccionaria, parte_entera = math.modf(decimal)
parte_entera = int(parte_entera)
cadena_parte_entera = ""
cadena_parte_fraccionaria = ""
while parte_entera > 0:
residuo = parte_entera % base
digito = digitos[int(residuo)]
cadena_parte_entera += digito
parte_entera = int(parte_entera/base)
# Invertir cadena de parte entera
# https://parzibyte.me/blog/2019/06/26/invertir-cadena-python/
cadena_parte_entera = cadena_parte_entera[::-1]
sobrante = None
# Un do while
# https://parzibyte.me/blog/2020/04/08/do-while-python/
while True:
resultado = parte_fraccionaria*base
parte_fraccionaria, sobrante = math.modf(resultado)
digito = digitos[int(sobrante)]
cadena_parte_fraccionaria += digito
if sobrante == 0:
break
return cadena_parte_entera + "." + cadena_parte_fraccionaria
Los comentarios explican el funcionamiento del método, pero básicamente recibe el número decimal que vamos a convertir, la base a la que vamos a convertir (por ejemplo, 2 para binario, 16 para hexadecimal, etcétera) y los dígitos que componen a la base.
Ahora te mostraré cómo usarla. Voy a convertir el mismo número a las 3 bases más usadas, aunque teóricamente se podría convertir a cualquier base.
decimal = 3722.24
en_binario = decimal_a_cualquier_base(decimal, 2, "01")
en_octal = decimal_a_cualquier_base(decimal, 8, "01234567")
en_hexadecimal = decimal_a_cualquier_base(decimal, 16, "0123456789ABCDEF")
print(f"El decimal {decimal} es {en_binario} en binario, {en_octal} en octal y {en_hexadecimal} en hexadecimal")
El código completo queda así, siéntete libre de modificarlo o mejorarlo. Recuerda que los datos de entrada pueden venir de cualquier lugar, aquí los estoy definiendo dentro del código por simplicidad.
import math
"""
Convertir el decimal con parte fraccionaria a cualquier base
decimal: el número decimal que se desea convertir. Por ejemplo, 12.34
base: la base a la que se desea convertir, si es binario es 2, octal 8, hexadecimal 16
digitos: los dígitos que componen a la base. Si es binario es "01", si es octal es "01234567", etcétera
https://parzibyte.me/blog
"""
def decimal_a_cualquier_base(decimal, base, digitos):
parte_fraccionaria, parte_entera = math.modf(decimal)
parte_entera = int(parte_entera)
cadena_parte_entera = ""
cadena_parte_fraccionaria = ""
while parte_entera > 0:
residuo = parte_entera % base
digito = digitos[int(residuo)]
cadena_parte_entera += digito
parte_entera = int(parte_entera/base)
# Invertir cadena de parte entera
# https://parzibyte.me/blog/2019/06/26/invertir-cadena-python/
cadena_parte_entera = cadena_parte_entera[::-1]
sobrante = None
# Un do while
# https://parzibyte.me/blog/2020/04/08/do-while-python/
while True:
resultado = parte_fraccionaria*base
parte_fraccionaria, sobrante = math.modf(resultado)
digito = digitos[int(sobrante)]
cadena_parte_fraccionaria += digito
if sobrante == 0:
break
return cadena_parte_entera + "." + cadena_parte_fraccionaria
decimal = 3722.24
en_binario = decimal_a_cualquier_base(decimal, 2, "01")
en_octal = decimal_a_cualquier_base(decimal, 8, "01234567")
en_hexadecimal = decimal_a_cualquier_base(decimal, 16, "0123456789ABCDEF")
print(f"El decimal {decimal} es {en_binario} en binario, {en_octal} en octal y {en_hexadecimal} en hexadecimal")
Si quieres puedes leer más sobre Python en mi blog.
Hoy te voy a presentar un creador de credenciales que acabo de programar y que…
Ya te enseñé cómo convertir una aplicación web de Vue 3 en una PWA. Al…
En este artículo voy a documentar la arquitectura que yo utilizo al trabajar con WebAssembly…
En un artículo anterior te enseñé a crear un PWA. Al final, cualquier aplicación que…
Al usar Comlink para trabajar con los workers usando JavaScript me han aparecido algunos errores…
En este artículo te voy a enseñar cómo usar un "top level await" esperando a…
Esta web usa cookies.
Ver comentarios
El código funciona muy bien y tiene la ventaja de servir para cualquier base.
PERO tiene un error en la linea 34, en vez de comparar con el sobrante (parte entera del resultado de parte_fraccionaria*base), debería verificar cuando la parte fraccionaria sea 0.
Porque de hecho en el ejemplo que esta usando 4722.24, no muestra nada de la parte fraccionaria en binario, porque apenas se encuentra un cero ya se detiene.
Solo habria que cambiar el if sobrante == 0 por el if parte_partefraccionario ==0.
PERO esto da un problema de que en algunos numeros puede ser infinito el patron de la parte fraccionaria, por eso deberia ponerse un limite.
puede ser añadirle una variable "precision" asi:
if parte_fraccionaria == 0 or i >= precision:
En conclusión quedaría algo como esto:
sobrante = None
i = 1
precision = 10
# Un do while
while True:
resultado = parte_fraccionaria*base
parte_fraccionaria, sobrante = modf(resultado)
digito = digitos[int(sobrante)]
cadena_parte_fraccionaria += digito
if parte_fraccionaria == 0 or i >= precision:
break
i += 1
return cadena_parte_entera + "." + cadena_parte_fraccionaria
Resultado:
El decimal 4722.24 es 1001001110010.0011110101 en binario, 11162.1727024365 en octal y 1272.3D70A3D70A en hexadecimal