[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Implementation of %
- From: Rici Lake <lua@...>
- Date: Wed, 18 May 2005 12:57:45 -0500
On 18-May-05, at 11:46 AM, Aaron Brown wrote:
Rici wrote:
Is there a good reason why % is implemented in terms of
floor rather than fmod? The following seems curiously
inconsistent to me:
I made a chart comparing math.mod(-6 through 6, -3 through
3) to (-6 through 6) % (-3 through 3). When the two give
different results, the math.mod result is to the left of the
colon.
It's pretty easy to summarize: math.mod (like fmod) returns a value
with the sign of the numerator (first argument). % returns a value
with the sign of the modulus (second argument).
Given the ieee-754 function copysign(x, y) (which returns x with
the sign of y), you can convert either behaviour into the other
one:
other_mod(n, m) == mod(copysign(n, m), copysign(m, n))
I'm not a big fan of the C behaviour, either (which afaik applies
to both integer % and fmod), although it is perfectly reasonable
if you consider % to be a remainder operator rather than a modulus
operator, which is its official name in the C standard (not that
that matters, really since this is Lua, not C). For what it's worth,
the C standard requires fmod to have the behaviour indicated above;
the original C spec did not state the result of % with negative
arguments (which has got to be the worst) and I believe that C99
requires % to behave like fmod (which is to say, actually be a
remainder).
The latest draft of IEEE-754 that I've seen also defines a
remainder operation rather than a modulus operator, although
its behaviour is even quirkier; the division is rounded to the
nearest integer, so that remainder(5,7) is -2.
So, as they say, the nice thing about standards is that there
are so many to choose from.
However, it seems to me that (x - (floor(x/y) * y) may do a
lot more work than I really wanted it to :) and might introduce
rounding errors, as well:
> -- A large random number
> a = 5465193658635553
> =math.mod(a, 2.1)
1.3688539491866
> =a%2.1
1
> -- % yields a negative result with positive arguments
> =math.mod(6.3, 2.1)
2.1
> =6.3%2.1
-8.8817841970013e-16
> -- Note the inexactness of 6.3 and 2.1:
> =string.format("%21.17f %21.17f", 6.3, 2.1)
6.29999999999999982 2.10000000000000009