Mercurial > cpython-lru_cache-weakref
diff Lib/rational.py @ 44899:cdc4aecedd4c legacy-trunk
Add first-cut at an approximation function (still needs rounding tweaks). Add continued fraction conversions.
| author | Raymond Hettinger <python@rcn.com> |
|---|---|
| date | Thu, 24 Jan 2008 00:54:21 +0000 |
| parents | c4709b81abde |
| children | cc73a8d1938b |
line wrap: on
line diff
--- a/Lib/rational.py Wed Jan 23 23:23:43 2008 +0000 +++ b/Lib/rational.py Thu Jan 24 00:54:21 2008 +0000 @@ -172,6 +172,42 @@ else: return cls(digits, 10 ** -exp) + @classmethod + def from_continued_fraction(cls, seq): + 'Build a Rational from a continued fraction expessed as a sequence' + n, d = 1, 0 + for e in reversed(seq): + n, d = d, n + n += e * d + return cls(n, d) + + def as_continued_fraction(self): + 'Return continued fraction expressed as a list' + n = self.numerator + d = self.denominator + cf = [] + while d: + e = int(n // d) + cf.append(e) + n -= e * d + n, d = d, n + return cf + + @classmethod + def approximate_from_float(cls, f, max_denominator): + 'Best rational approximation to f with a denominator <= max_denominator' + # XXX First cut at algorithm + # Still needs rounding rules as specified at + # http://en.wikipedia.org/wiki/Continued_fraction + cf = cls.from_float(f).as_continued_fraction() + result = new = Rational(0, 1) + for i in range(1, len(cf)): + new = cls.from_continued_fraction(cf[:i]) + if new.denominator > max_denominator: + break + result = new + return result + @property def numerator(a): return a._numerator
