From: David Masover Date: 2009-11-22T16:14:28+09:00 Subject: Re: really crazy about this (do/while) On Saturday 21 November 2009 09:21:59 pm Florian Frank wrote: > Welcome to the wonderful world of floating point numbers: > >> 98.4 + 0.1 + 0.1 < 98.6 > > # => false > > >> 98.3 + 0.1 + 0.1 + 0.1 < 98.6 > > # => true If you want accuracy, and don't care about performance, you could always use rationals (fractions): >> Rational(983,10) + Rational(1,10) + Rational(1,10) + Rational(1,10) < Rational(986,10) => false Of course, beware of trying to convert from floats to rationals: >> Rational(98.3) => (6917247552664371/70368744177664) If you look carefully: >> Rational(98.3).denominator == 2**46 => true That also explains why floats behave strangely in general, for the newbies out there. When we see 98.3, we see 98 and 3/10ths. But the computer doesn't use 10ths any more than it uses 10s, 100s, etc. It uses binary, powers of two. So it converts those 3/10ths to some fraction of a power of two. Unless, of course, you're on a mainframe. Then you can do packed decimal arithmetic... But it'll be slower and perversely hard to work with for other reasons. So my compromise is, when I want to work with some fraction of a number, and I want it to be as precise as possible (with no regard for performance), I make it a Rational as long as I can get away with. I can always call to_f on the end result. I might be Doing It Wrong, though. Maybe BigDecimal is the way to go?