fractions.Fraction.from_number() permite crear fracciones exactas a partir de objetos numéricos compatibles. Es útil cuando una aplicación necesita conservar la relación entre numerador y denominador, evitar redondeos prematuros y dejar claro que la entrada ya es un número y no una cadena que debe analizarse.
Qué es Fraction
La clase Fraction del módulo fractions representa números racionales mediante un numerador entero y un denominador entero. A diferencia de los valores de punto flotante binario, una fracción puede conservar muchas proporciones de manera exacta. Esto resulta útil en matemáticas, pruebas, conversiones, probabilidades, repartos y reglas donde la proporción importa más que la velocidad.
Puedes repasar las bases en nuestras guías sobre tipos de datos en Python, operadores de Python y el curso completo de Python.
Uso básico
from fractions import Fraction
valor = Fraction.from_number(5)
print(valor) # 5
Un entero se convierte en una fracción con denominador uno. Un objeto racional compatible mantiene su proporción exacta. El método comunica que la fuente es numérica.
Conversión de float
Los valores float se almacenan en formato binario. Por eso, al convertir 0.1, el resultado representa exactamente el valor binario guardado y no necesariamente la fracción decimal simple 1/10.
from fractions import Fraction
valor = Fraction.from_number(0.1)
print(valor)
print(valor.limit_denominator())
Un numerador y denominador grandes no indican un error. Cuando una aproximación sencilla es aceptable, limit_denominator() puede limitar el denominador. La documentación oficial explica la representación de punto flotante y el módulo fractions.
Conversión desde Decimal
Decimal suele ser una mejor fuente cuando el valor decimal debe conservarse de manera predecible. Por ejemplo, Decimal('0.125') representa exactamente un octavo.
from decimal import Decimal
from fractions import Fraction
cantidad = Decimal('0.125')
fraccion = Fraction.from_number(cantidad)
print(fraccion) # 1/8
Este enfoque es apropiado para precios, tasas y datos decimales introducidos por usuarios. Consulta también nuestra guía de Decimal en Python.
Números frente a cadenas
from_number() está pensado para objetos numéricos. Para textos como '3/7' o '0.25', el constructor tradicional Fraction() sigue siendo la opción correcta.
from fractions import Fraction
desde_texto = Fraction('3/7')
desde_numero = Fraction.from_number(0.25)
La separación mejora la legibilidad: un texto debe analizarse, mientras que un número se convierte según su protocolo numérico.
Validación y errores
Las entradas externas deben validarse. Una función auxiliar puede transformar excepciones internas en mensajes más claros:
from fractions import Fraction
def como_fraccion(valor):
try:
return Fraction.from_number(valor)
except (TypeError, ValueError) as error:
raise ValueError(f'Valor numérico inválido: {valor!r}') from error
Este patrón funciona bien en APIs, procesos de datos, herramientas de línea de comandos y bibliotecas. Revisa nuestra guía sobre manejo de errores en Python.
Aritmética exacta
from fractions import Fraction
a = Fraction.from_number(3)
b = Fraction(1, 4)
print(a + b)
print(a * b)
print(a / b)
Los resultados siguen siendo racionales siempre que sea posible. Esto ayuda en intervalos musicales, proporciones geométricas, recetas, reparto de recursos, combinatoria y algoritmos que no deben acumular errores de punto flotante.
Cuándo elegir otro tipo
Fraction no siempre es la mejor alternativa. Los arreglos científicos, modelos de aprendizaje automático, simulaciones y gráficos suelen beneficiarse del rendimiento de float y bibliotecas vectorizadas. Los sistemas financieros a menudo prefieren Decimal porque sus reglas se expresan en posiciones decimales y modos de redondeo.
Utiliza fracciones cuando la relación racional exacta sea más importante que el rendimiento. Evita conversiones repetidas en bucles críticos y mide el comportamiento con datos reales.
Aproximaciones controladas
limit_denominator(max_denominator) permite convertir una representación compleja en una aproximación comprensible. El límite correcto depende del contexto. Para tiempo puede ser útil 60; para medidas comunes, 8, 16 o 1000. No debe aplicarse sin criterio porque modifica intencionalmente el valor exacto.
from fractions import Fraction
original = Fraction.from_number(3.141592653589793)
aprox = original.limit_denominator(1000)
print(aprox) # 355/113
Pruebas recomendadas
Incluye enteros, negativos, cero, valores Decimal, floats con representación binaria sorprendente y objetos no compatibles. Cuando uses aproximaciones, verifica la tolerancia o el denominador esperado en lugar de depender de una representación interna específica.
También debes evitar asumir que convertir una fracción a float y luego volver a fracción recuperará siempre el valor original. El paso intermedio puede perder información.
Rendimiento
La aritmética con fracciones normaliza resultados y puede generar enteros grandes. Operaciones repetidas aumentan el tamaño del numerador y denominador, lo que puede ser más lento que el punto flotante. Reduce conversiones, perfila el código y reserva las fracciones para los límites donde la exactitud es realmente necesaria.
Buenas prácticas
Usa enteros y Decimal cuando necesites una proporción simple y exacta. Documenta las conversiones desde float. Aplica limit_denominator() solo cuando la aproximación sea válida. Valida entradas no confiables, trata tipos incompatibles y define claramente la política numérica del proyecto.
Nombres como proporcion, cuota o tasa_conversion expresan mejor el significado que variables genéricas. Una fracción es más útil cuando el código explica qué representa cada parte.
Conclusión
Fraction.from_number() hace explícita la conversión de números a valores racionales. Conserva relaciones exactas cuando es posible, diferencia entradas numéricas y textuales y se integra con enteros, floats y Decimal. Con validación, límites de aproximación, pruebas y una elección consciente del tipo numérico, ofrece una base fiable para cálculos racionales exactos en Python.







