La naturaleza de los números de punto flotante significa que no tiene sentido a cheque si un número de coma flotante es racional, ya que todos los números de punto flotante son realmente fracciones de la forma n/2 correo. Sin embargo, es posible que desee saber si hay simple fracción (una con un denominador pequeño en lugar de una gran potencia de 2) que se aproxima mucho a un número de punto flotante dado.
Donald Knuth discute este último problema en The Art of Computer Programming volumen II. Vea la respuesta al ejercicio 4.53-39. La idea es buscar la fracción con el denominador más bajo dentro de un rango, expandiendo los puntos finales del rango como fracciones continuas siempre que sus coeficientes sean iguales, y luego cuando difieran, tome el valor más simple entre ellos. He aquí una aplicación bastante sencilla en Python:
from fractions import Fraction
from math import modf
def simplest_fraction_in_interval(x, y):
"""Return the fraction with the lowest denominator in [x,y]."""
if x == y:
# The algorithm will not terminate if x and y are equal.
raise ValueError("Equal arguments.")
elif x < 0 and y < 0:
# Handle negative arguments by solving positive case and negating.
return -simplest_fraction_in_interval(-y, -x)
elif x <= 0 or y <= 0:
# One argument is 0, or arguments are on opposite sides of 0, so
# the simplest fraction in interval is 0 exactly.
return Fraction(0)
else:
# Remainder and Coefficient of continued fractions for x and y.
xr, xc = modf(1/x);
yr, yc = modf(1/y);
if xc < yc:
return Fraction(1, int(xc) + 1)
elif yc < xc:
return Fraction(1, int(yc) + 1)
else:
return 1/(int(xc) + simplest_fraction_in_interval(xr, yr))
def approximate_fraction(x, e):
"""Return the fraction with the lowest denominator that differs
from x by no more than e."""
return simplest_fraction_in_interval(x - e, x + e)
Y aquí están algunos resultados:
>>> approximate_fraction(6.75, 0.01)
Fraction(27, 4)
>>> approximate_fraction(math.pi, 0.00001)
Fraction(355, 113)
>>> approximate_fraction((1 + math.sqrt(5))/2, 0.00001)
Fraction(377, 233)
Irracionales no pueden ser representados por razón (nal) s, ¡esa misma definición y la fuente del nombre! – delnan
@delnan, FWIW, se pueden representar como racionales. Ambos métodos de uso común para hacerlo formalmente (cortes de Dedekind y series de Cauchy) usan racionales para hacerlo. Simplemente usan una cantidad infinita de racionales :) – aaronasterling
Para una verdadera diversión, busca fracciones continuas. Para implementar una solución usted mismo, haga la fracción continua hasta que resulte en una fracción exacta o el denominador sea demasiado grande para su gusto. – phkahler