Luke Galea
5/6/2005 2:43:00 PM
Thanks for all the great responses!
So.. I guess the next question is: Does everyone think this is a worthwhile
addition to the Ruby STDLib?If so, how do we go about getting it added to
Rational.rb?
On Thursday 05 May 2005 17:27, Mark Hubbart wrote:
> On 5/5/05, Christoph <chr_mail@gmx.net> 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