From: Mark Hubbart Date: 2005-05-06T06:27:31+09:00 Subject: Re: Float to Rational On 5/5/05, Christoph wrote: > Zane Dodson schrieb: > > >Knuth has a discussion of this in `Seminumerical Algorithms, The Art > >of Computer Programming, vol. 2.' > > > >In the third edition, it is in sec. 4.5.3 (pp. 356ff). See also > >exercise 4.5.3.2 > > > > > Florian's solution is of course nothing but continued fraction > - without the (relative) error term he could be into a long wait > calling #to_r unless he is very lucky .. Thanks to those who mentioned the "continued fractions" method. Here's a new implementation: ---- require 'mathn' class Numeric def inverse 1/self end end class Float def to_r n = 1 n *= 2 until (self*n) % 1 == 0 (self*n).to_i/n end def round_to_r return self.to_i if self % 1 == 0 n = self ops = [] count = 0 until ((n%1).round - n%1).abs < 1e-8 || count > 20 || n.abs == 1.0/0.0 || n == 0.0/0.0 int, dec = n.divmod 1 ops.concat [[:+, int.to_i], [:inverse]] n = 1/dec count += 1 end n = n.round ops.reverse.inject(n.round){|n, op| n.send(*op)} end end ---- Use Float#to_r for an exact representation of the float value, or Float#round_to_r for an extremely close representation of it. cheers, Mark