fractions en Python: números racionales

Publicado el: 31/07/2026
Tempo de leitura: 6 minutos
Gráficos de fracciones que representan números racionales exactos en Python

Las fracciones aparecen en recetas, proporciones, escalas, música, probabilidades, conversiones y algoritmos matemáticos. Usar float para representar 1/3 o 2/7 produce aproximaciones, mientras Decimal tampoco conserva exactamente los racionales periódicos. El módulo fractions en Python ofrece la clase Fraction, que almacena numerador y denominador enteros y mantiene aritmética racional exacta.

Esta guía explica construcción desde enteros, cadenas, Decimal y floats, reducción automática, limit_denominator(), formateo, validación y la elección entre Fraction, Decimal y float. Complementa nuestros artículos sobre floats en Python, Decimal, enteros, tipos de datos y formato con f-strings.

Qué es un número racional

Un número racional puede escribirse como razón de dos enteros, con denominador distinto de cero. Ejemplos: 1/2, -7/3, 5 y 0.125. La clase Fraction conserva esa estructura:

from fractions import Fraction

mitad = Fraction(1, 2)
tercio = Fraction(1, 3)

print(mitad)
print(tercio)

Las instancias son inmutables y hashable, por lo que pueden usarse como claves de diccionario y elementos de conjuntos.

Normalización automática

El constructor reduce la razón a sus términos mínimos y mantiene el denominador positivo.

from fractions import Fraction

print(Fraction(16, -10))  # -8/5
print(Fraction(20, 30))   # 2/3

El módulo usa el máximo común divisor. No necesitas simplificar manualmente cada resultado.

Crear Fraction desde cadenas

Las cadenas conservan la intención textual:

from fractions import Fraction

print(Fraction("3/7"))
print(Fraction(" -3 / 7 "))
print(Fraction("0.125"))
print(Fraction("7e-6"))

Desde Python 3.12 se permiten espacios alrededor de la barra. Las cadenas decimales finitas se convierten en razones exactas, como 0.125 = 1/8.

Construcción desde float

Un float se convierte a su valor binario exacto, no necesariamente a la fracción decimal esperada.

from fractions import Fraction

print(Fraction(1.1))
# 2476979795053773/2251799813685248

La causa se explica en el tutorial oficial de punto flotante: 1.1 no posee representación binaria finita. Usa Fraction("1.1") o Fraction(11, 10) para once décimos exactos.

Fraction desde Decimal

Un Decimal finito se convierte exactamente:

from decimal import Decimal
from fractions import Fraction

valor = Fraction(Decimal("1.1"))
print(valor)  # 11/10

Es útil cuando la entrada ya fue validada como decimal, pero el algoritmo necesita una razón exacta.

from_number() en Python 3.14

Python 3.14 añade Fraction.from_number(). Acepta enteros, racionales, floats, Decimal y objetos con as_integer_ratio(), pero no cadenas.

from fractions import Fraction

print(Fraction.from_number(5))
print(Fraction.from_number(2.25))

La conversión de float sigue conservando el valor binario exacto. La API hace explícito el contrato de entrada numérica.

Aritmética exacta

from fractions import Fraction

a = Fraction(1, 3)
b = Fraction(1, 6)

print(a + b)  # 1/2
print(a - b)  # 1/6
print(a * b)  # 1/18
print(a / b)  # 2

Los resultados permanecen normalizados. Las potencias con exponentes enteros también funcionan.

numerator y denominator

Los atributos de solo lectura exponen los componentes reducidos:

valor = Fraction(42, 56)
print(valor.numerator)    # 3
print(valor.denominator)  # 4

El denominador siempre es positivo y el signo queda en el numerador.

Recuperar una razón legible desde float

limit_denominator() encuentra la fracción más cercana cuyo denominador no supera un límite.

from fractions import Fraction

aproximacion = Fraction(1.1).limit_denominator()
print(aproximacion)  # 11/10

La documentación oficial de fractions también muestra la aproximación 355/113 para pi con un denominador máximo de 1000.

pi_aprox = Fraction("3.141592653589793").limit_denominator(1000)
print(pi_aprox)  # 355/113

Elegir max_denominator

El límite debe reflejar el dominio. Una receta puede necesitar denominadores hasta 16, mientras una aproximación científica puede necesitar miles.

valor = Fraction("0.3332")
print(valor.limit_denominator(10))
print(valor.limit_denominator(1000))

Un límite mayor mejora la cercanía, pero puede producir razones difíciles de interpretar. Define un error aceptable y compruébalo.

Comprobar si es entero

Desde Python 3.12, is_integer() indica si el denominador reducido es uno.

print(Fraction(6, 3).is_integer())  # True
print(Fraction(7, 3).is_integer())  # False

int() trunca hacia cero, por lo que no sirve como prueba de integralidad.

floor, ceil y round

Fraction se integra con las funciones estándar:

import math
from fractions import Fraction

valor = Fraction(7, 3)
print(math.floor(valor))
print(math.ceil(valor))
print(round(valor, 2))

round() usa empates al par. Con ndigits, el resultado sigue siendo Fraction.

Formato con f-strings

Las versiones recientes ampliaron el formato. Desde 3.12 se admiten tipos como f, e, g y porcentaje.

valor = Fraction(1, 7)
print(f"{valor:.6f}")
print(f"{valor:.2%}")

Python 3.13 añadió alineación, signo, ancho y agrupación sin tipo de presentación.

print(f"{Fraction(103993, 33102):_}")
print(f"{Fraction(3, 1):#}")

La opción # fuerza un denominador explícito incluso en enteros.

Comparación y ordenación

Las fracciones se comparan con enteros, floats y Decimal, aunque los floats reflejan aproximación binaria.

valores = [Fraction(2, 3), Fraction(1, 2), Fraction(3, 4)]
print(sorted(valores))

Normaliza los tipos cuando importan reglas exactas.

Recetas y proporciones

cantidad_base = Fraction(3, 4)
factor = Fraction(5, 2)
cantidad = cantidad_base * factor
print(cantidad)  # 15/8

Para mostrar, separa parte entera y resto:

entero = cantidad.numerator // cantidad.denominator
resto = cantidad - entero
print(entero, resto)

Probabilidades exactas

Las fracciones funcionan bien en espacios muestrales pequeños:

favorables = 6
posibles = 36
probabilidad = Fraction(favorables, posibles)
print(probabilidad)  # 1/6

Los modelos grandes pueden crear enteros enormes. Para estadística a escala, float y bibliotecas vectorizadas suelen ser mejores.

Conversiones de unidades

Los factores racionales evitan error acumulado:

pulgadas_por_pie = Fraction(12, 1)
pies = Fraction(5, 2)
pulgadas = pies * pulgadas_por_pie
print(pulgadas)  # 30

La exactitud no evita mezclar unidades incorrectamente; documenta y valida las unidades.

Crecimiento de numerador y denominador

Las operaciones repetidas pueden crear enteros muy grandes. La normalización elimina factores comunes, pero no limita la magnitud.

valor = Fraction(1, 1)
for n in range(2, 50):
    valor += Fraction(1, n)
print(len(str(valor.numerator)))

Este crecimiento aumenta CPU y memoria. Los algoritmos aproximados pueden aplicar limit_denominator() en límites controlados o usar otro tipo.

Fraction frente a Decimal

Usa Fraction cuando el valor es naturalmente una razón exacta, como 1/3, escalas o probabilidades combinatorias. Usa Decimal cuando el dominio trabaja con posiciones decimales, dinero y reglas de redondeo.

Decimal representa 0.1 exactamente, pero debe redondear 1/3. Fraction conserva 1/3 exacto, pero reduce 0.10 a 1/10 y no guarda ceros significativos.

Fraction frente a float

Float es mucho más rápido y se integra con NumPy, gráficos y bibliotecas científicas. Fraction está pensado para aritmética racional exacta en volúmenes moderados.

No conviertas a float en medio de un cálculo exacto y esperes recuperar después la razón original. Mantén la conversión en la frontera y documenta tolerancias.

Serialización

JSON no tiene un tipo Fraction nativo. Una representación explícita evita ambigüedad:

registro = {
    "numerator": valor.numerator,
    "denominator": valor.denominator,
}

También puedes enviar "3/4" si el contrato define el formato. No envíes solo una aproximación float cuando debe conservarse exactitud.

Validación de entrada

Captura ValueError para cadenas inválidas y ZeroDivisionError para denominador cero.

def leer_fraccion(texto: str) -> Fraction:
    try:
        return Fraction(texto)
    except (ValueError, ZeroDivisionError) as error:
        raise ValueError("Fracción inválida") from error

Impone límites de tamaño a datos no confiables. Enteros con millones de dígitos pueden consumir recursos excesivos.

Pruebas de cálculos racionales

assert Fraction(1, 3) + Fraction(1, 6) == Fraction(1, 2)
assert Fraction("0.125") == Fraction(1, 8)
assert Fraction(1.1).limit_denominator() == Fraction(11, 10)

Prueba signos, denominador cero, parsing, formato y límites de aproximación.

Errores frecuentes

  • Usar Fraction(1.1) esperando 11/10.
  • Permitir denominadores ilimitados desde entrada no confiable.
  • Usar Fraction para dinero y perder la escala decimal.
  • Convertir a float demasiado pronto.
  • Interpretar int(fraccion) como redondeo.
  • Elegir un límite sin medir el error.
  • Serializar solo una aproximación decimal.
  • Ignorar el crecimiento de enteros.

Buenas prácticas

  • Construye valores exactos desde enteros o cadenas.
  • Prefiere Decimal cuando la escala decimal forma parte del contrato.
  • Define límites según el dominio.
  • Mantén Fraction en el núcleo exacto.
  • Valida entrada y tamaño.
  • Serializa numerador y denominador.
  • Mide rendimiento en bucles grandes.
  • Prueba aproximaciones y negativos.

Conclusión

El módulo fractions en Python ofrece aritmética racional exacta integrada con el modelo numérico de la lengua. Fraction normaliza automáticamente, acepta varias entradas, ofrece aproximaciones controladas y admite formato moderno.

El tipo adecuado depende del dominio. Fraction conserva razones como 1/3, Decimal conserva valores decimales y reglas monetarias, y float prioriza rendimiento e integración numérica. Elegir el tipo correcto evita aproximaciones innecesarias y produce resultados más claros, comprobables y fáciles de explicar.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    Calculadora y documentos que representan cálculos Decimal precisos en Python
    Bibliotecas y Módulos
    Foto de perfil de Leandro Hirt da Academify

    Decimal en Python: cálculos precisos

    Aprende Decimal en Python para cálculos exactos, dinero, quantize, redondeo, contextos y validación sin errores de float.

    Ler mais

    Tempo de leitura: 7 minutos
    30/07/2026
    Código digital que representa identificadores UUID únicos y ordenables en Python
    Bibliotecas y Módulos
    Foto de perfil de Leandro Hirt da Academify

    uuid en Python: IDs únicos y ordenables

    Aprende uuid en Python: versiones 4, 5, 6 y 7, validación, almacenamiento, IDs ordenables y buenas prácticas de seguridad.

    Ler mais

    Tempo de leitura: 7 minutos
    30/07/2026
    Archivos organizados que representan almacenamiento temporal seguro en Python
    Bibliotecas y Módulos
    Foto de perfil de Leandro Hirt da Academify

    tempfile en Python: archivos temporales

    Aprende tempfile en Python para crear archivos y carpetas temporales seguros, con limpieza automática en Windows y Unix.

    Ler mais

    Tempo de leitura: 8 minutos
    29/07/2026
    Relojes que representan zonas horarias internacionales con zoneinfo en Python
    Bibliotecas y Módulos
    Foto de perfil de Leandro Hirt da Academify

    zoneinfo en Python: zonas horarias

    Aprende zoneinfo en Python para convertir zonas, tratar horario de verano, fold, UTC y tzdata sin errores de programación.

    Ler mais

    Tempo de leitura: 7 minutos
    29/07/2026
    Icono de documentos duplicados que representa copias superficiales y profundas en Python
    Bibliotecas y Módulos
    Foto de perfil de Leandro Hirt da Academify

    copy en Python: copia superficial y profunda

    Aprende copy en Python para crear copias superficiales, profundas y reemplazar campos sin compartir objetos mutables por error.

    Ler mais

    Tempo de leitura: 7 minutos
    28/07/2026
    Monitor con búsqueda binaria y listas ordenadas en Python
    Bibliotecas y Módulos
    Foto de perfil de Leandro Hirt da Academify

    bisect en Python: listas siempre ordenadas

    Aprende bisect en Python para mantener listas ordenadas, localizar rangos, encontrar vecinos e insertar valores con búsqueda binaria.

    Ler mais

    Tempo de leitura: 9 minutos
    27/07/2026