From: Morton Goldberg Date: 2007-08-30T20:22:32+09:00 Subject: Re: Bug in % (Float)? On Aug 30, 2007, at 3:39 AM, Calamitas wrote: > On 30/08/2007, Morton Goldberg wrote: >> On Aug 29, 2007, at 10:14 PM, Pe�a, Botp wrote: >> >>> From: Charlie Lehardy [mailto:charlie.lehardy@gmail.com] : >>> # irb(main):001:0> 1 % 0.1 >>> # => 0.1 >>> # >>> # Shouldn't 1 % 0.1 be 0.0 and not 0.1? >>> >>> never trust floats in division :) >>> ruby tries to be friendly at the expense of more surprises... >>> >>> irb(main):343:0> system "qri numeric.divmod | head -7" >>> --------------------------------------------------------- >>> Numeric#divmod >>> num.divmod( aNumeric ) -> anArray >>> -------------------------------------------------------------------- >>> -- >>> -- >>> Returns an array containing the quotient and modulus >>> obtained by >>> dividing num by aNumeric. If q, r = x.divmod(y), then >>> >>> q = floor(float(x)/float(y) >>> >>> irb(main):345:0> 1.divmod 0.1 >>> => [9, 0.1] >> >> If Numeric#divmod adhered to the above, the result would be [10.0, >> 0.0], so the result is just plain wrong, not a matter of float >> inaccuracy. Proof: >> >> x, y = 1.0, 0.1 >> (x/y).floor.to_f # => 10.0 >> >>> irb(main):347:0> 9*0.1+0.1 >>> => 1.0 I going to be stubborn about this. > Mathematically, division goes as follows: > > given a dividend n, a divisor d, the quotient q and remainder r are > defined as follows: > > n = q * d + r > 0 <= r < d > > The only number required to be integer to make the solution to the > equations unique is q. No, that only holds for _integer_ division. For fields (e.g., real numbers), division is defined as the inverse of multiplication. For computer floats, which are neither integers nor form a field, defining a modulo operator is tricky (as I said in previous post). But it can be done better than Ruby is doing it. A reasonable definition for a float modulo would be: def m_mod_n(m, n) m - n * m.quo(n) end With this definition m_mod_n(1.0, 0.1) # => 0.0 > In floating point arithmetic, the first equation is approximately > true, usually in as close a way as possible in a certain sense. The > second equation is strictly adhered to, you can check: > > irb(main):001:0> 1.0 % 0.1 < 0.1 > => true > > As for the equation given by ri, it's not intended to be evaluated by > Ruby (note how you needed to change where you put the floor function.) > Since 0.1 is represented by a float float(0.1) that is slightly larger > than 0.1, and 1.0 i represented exactly by float(1.0), float(1.0) / > float(0.1) will be slightly smaller than 10 in exact arithmetic, > rounding down gives 9. As your example demonstrates, that's a bad algorithm and should not be used. Regards, Morton