fractions — Números racionales

Propósito:Implementa una clase para trabajar con números racionales.

La clase Fraction implementa operaciones numéricas para números racionales basados en la interfaz definida por Rational en el módulo numbers.

Creando instancias de Fraction

Al igual que con el módulo decimal, se pueden crear nuevos valores de varias formas. Una manera fácil es crearlos a partir de los valores separados de numerador y denominador:

fractions_create_integers.py
import fractions

for n, d in [(1, 2), (2, 4), (3, 6)]:
    f = fractions.Fraction(n, d)
    print('{}/{} = {}'.format(n, d, f))

El mínimo común denominador se mantiene a medida que nuevos valores son calculados.

$ python3 fractions_create_integers.py

1/2 = 1/2
2/4 = 1/2
3/6 = 1/2

Otra forma de crear un Fraction es usar una representación de cadena de <numerador> / <denominador>:

fractions_create_strings.py
import fractions

for s in ['1/2', '2/4', '3/6']:
    f = fractions.Fraction(s)
    print('{} = {}'.format(s, f))

La cadena se analiza para encontrar los valores de numerador y denominador.

$ python3 fractions_create_strings.py

1/2 = 1/2
2/4 = 1/2
3/6 = 1/2

Las cadenas también pueden usar la notación decimal o de coma flotante más habitual de series de dígitos separados por un punto. Cualquier cadena que pueda ser analizado por float() y que no representa un «no un número» (NaN) o un valor infinito es compatible.

fractions_create_strings_floats.py
import fractions

for s in ['0.5', '1.5', '2.0', '5e-1']:
    f = fractions.Fraction(s)
    print('{0:>4} = {1}'.format(s, f))

Los valores de numerador y denominador representados por valores de coma flotante se calculan automáticamente.

$ python3 fractions_create_strings_floats.py

 0.5 = 1/2
 1.5 = 3/2
 2.0 = 2
5e-1 = 1/2

También es posible crear instancias de Fraction directamente de otras representaciones de valores racionales, como float o Decimal.

fractions_from_float.py
import fractions

for v in [0.1, 0.5, 1.5, 2.0]:
    print('{} = {}'.format(v, fractions.Fraction(v)))

Los valores de coma flotante que no se pueden expresar exactamente pueden producir resultados inesperados.

$ python3 fractions_from_float.py

0.1 = 3602879701896397/36028797018963968
0.5 = 1/2
1.5 = 3/2
2.0 = 2

Usar representaciones Decimal de los valores da el resultado inesperados.

fractions_from_decimal.py
import decimal
import fractions

values = [
    decimal.Decimal('0.1'),
    decimal.Decimal('0.5'),
    decimal.Decimal('1.5'),
    decimal.Decimal('2.0'),
]

for v in values:
    print('{} = {}'.format(v, fractions.Fraction(v)))

La implementación interna de Decimal no sufre de los errores de precisión de la representación de coma flotante estándar.

$ python3 fractions_from_decimal.py

0.1 = 1/10
0.5 = 1/2
1.5 = 3/2
2.0 = 2

Aritmética

Una vez que las fracciones se instancian, se pueden usar en expresiones matemáticas.

fractions_arithmetic.py
import fractions

f1 = fractions.Fraction(1, 2)
f2 = fractions.Fraction(3, 4)

print('{} + {} = {}'.format(f1, f2, f1 + f2))
print('{} - {} = {}'.format(f1, f2, f1 - f2))
print('{} * {} = {}'.format(f1, f2, f1 * f2))
print('{} / {} = {}'.format(f1, f2, f1 / f2))

Todos los operadores estándar son compatibles.

$ python3 fractions_arithmetic.py

1/2 + 3/4 = 5/4
1/2 - 3/4 = -1/4
1/2 * 3/4 = 3/8
1/2 / 3/4 = 2/3

Valores aproximados

Una característica útil de Fraction es la capacidad de convertir un número de coma flotante a un valor racional aproximado.

fractions_limit_denominator.py
import fractions
import math

print('PI       =', math.pi)

f_pi = fractions.Fraction(str(math.pi))
print('No limit =', f_pi)

for i in [1, 6, 11, 60, 70, 90, 100]:
    limited = f_pi.limit_denominator(i)
    print('{0:8} = {1}'.format(i, limited))

El valor de la fracción se puede controlar limitando el tamaño de el denominador.

$ python3 fractions_limit_denominator.py

PI       = 3.141592653589793
No limit = 3141592653589793/1000000000000000
       1 = 3
       6 = 19/6
      11 = 22/7
      60 = 179/57
      70 = 201/64
      90 = 267/85
     100 = 311/99

Ver también