lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


In message <003301c1891b$8fde08e0$0300a8c0@CORWIN>, "Peter Hill" writes:
> John Mckenna replied:
> > You have floor() and ceil().  They can be used to do any integerising you
> > need.
> >
> > I can never remember how mod is supposed to work when negative numbers are
> > involved, so this might only work for positive numbers (that's all I ever
> > use mod for anyway):
> >
> > result = a - b*floor(a/b)
> 
> 
> Scott Morgan added:
> >  http://www.lua.org/manual/manual.html#6.3
> > The 'mod' function is there, and appears in Plua.
> 
> 
> You can get the "remainder" using EITHER "a-b*floor(a/b)" or "mod(a,b)"
> however there IS a difference.
> 
> (a) "function rem(a,b) return a-b*floor(a/b) end" will always handle
> negative numbers in a well defined and (generally) more useful fashion.
> Specifically, the result always falls in the range [0,b).
> 
> (b) "mod" is, AFAIK, machine dependent (based on the hardware operations?)
> and under PLua implements a common (but generally less useful) definiton. In
> essence it depends on how you wish to round your integer division. Ie,
>     2/5 = 0.4, which is universally considered to be "0 remainder 2".
> but
>     -2/5 = -0.4 which can be considered to be (a) "0 remainder -2" (since -2
> = -1x5 + 3) or (b) "-1 remainder 3" (since -2 = 1x5 + -2).
> 
> Thus (under PLua):
>     rem(-2,5) = 3   [using "rem" defined above]
> versus
>     mod(-2,5) = -2   [using the machine-dependent version]
> 
> Which you use depends on why you want the remainder.
> 
> For example, if I wanted to create a hash table in C mapping an arbitrary
> integer "x" onto a C array "type hash_table[47];" then I would use
> "rem(x,47)" to get the index as it produces a result 0..46 for all values of
> "x" including negative ones.

In lua, using its standard math library mod is defined in terms of C's
fmod.  This is well defined ([1]) and the result of fmod(x, y) is the
remainder of x/y that has the same sign as x (which is what you also
call mod above).

Scheme has both functions (and names them the other way around):

>From the R5RS (Scheme definition)
http://www.swiss.ai.mit.edu/~jaffer/r5rs_8.html#SEC55
:

    (quotient n1 n2)                   ==> n_q
    (remainder n1 n2)                  ==> n_r
    (modulo n1 n2)                     ==> n_m


  where n_q is n1/n2 rounded towards zero, 0 < |n_r| < |n2|, 0 < |n_m| <
  |n2|, n_r and n_m differ from n1 by a multiple of n2, n_r has the same
  sign as n1, and n_m has the same sign as n2. 

Note their rather witty and concise formulation of the difference
between remainder and modulo: remainder has the same sign as the first
argument, modulo has the same sign as the second argument.

Scheme's naming of these two functions is also my preferred naming.
Shame the rest of the world seems to disagree.

Pop quiz: Why would anyone want to use scheme's remainder function (or
equivalently lua's mod function) rather than the other variant?

Cheers,
 drj




Footnotes

1. fmod(x, 0) is not well defined.