On 30/08/2007, Morton Goldberg <m_goldberg / ameritech.net> wrote:
> On Aug 30, 2007, at 3:39 AM, Calamitas wrote:
>
> > On 30/08/2007, Morton Goldberg <m_goldberg / ameritech.net> 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.

That definition works (i.e. it defines q and r uniquely) for real
numbers too, provided that q is required to be integer. But that was
not my point, my point was that the condition that r.abs should be
minimal is not the usual one.

> 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

This returns 0.0 for m_mod_n(1.0, 0.3) too. Is that the intention?

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

The ideal for floating point arithmetic is that the operations are
performed in real arithmetic (floating point numbers are a subset of
real numbers, so that's an exact operation), and the result is then
taken to be the floating point number closest to the real result.
That's what the expression given by ri expresses, and I don't think
you can really ask for anything better. In Ruby 0.1 really is
0.10000000000000000555 as that is the floating point number closest to
0.1, and it doesn't fit 10 whole times in 1.0. This has nothing to do
with the algorithm used.

Peter