[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Re: Float to Rational

Eric Mahurin

5/6/2005 12:23:00 PM

Here is another simple way I came up with. This shouldn't be
any less accurate than the to_r you have since the error in the
mantissa is at least 1 mantissa bit (I'm assuming 50 mantissa
bits). The difference between this and what you had was you
only multiplied by 2 forcing the denominator to be a power of 2
and you waited until the numerator was exactly an integer.
17.0/37 seems to be the float with the smallest denominator
that starts giving problems in this algorithm. Another
possibility would be to test incrementing/decrementing the
numerator and/or denominator to see if you get a simpler
rational. This should be valid since you know that mantissa
error translates to numerator/denominator error.

require 'mathn'

class Float

Err = 2.0**-50

def to_r
num = self
denominator = 1
loop do
# factors needed to get denominators 2-36 (sometimes 37)
[2,3,2,5,7,2,3,11,13,2,17,19,23,5,3,29,31,2,37].each do
|f|
if (1-num/(numerator=num.round)).abs<=Err
return numerator/denominator
end
denominator *= f
num *= f
end
end
end

end


> 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
>
>




Yahoo! Mail
Stay connected, organized, and protected. Take the tour:
http://tour.mail.yahoo.com/mai...