modulus fn with negatives

cosell at BBN-LABS-B.ARPA cosell at BBN-LABS-B.ARPA
Mon Sep 10 12:42:27 AEST 1984


I has been my observation (over quite a few machines) that all you can hope for
is that '/' and '%' agree.  That is, for any I and M, all you can count on is
that I = (I/M) * M + (I%M).  This may seem obvious, but it is certainly
possible to bollix up the signs of things so that, for example, you might have
I = ... '+' I%M if M>0, but I = ... '-' I%M if M<0.  In any event, the few
hardware folk I've talked to about this seem to believe that once the above
'reassembly' equation is satisfied, they don't care any more.  Mostly I've
found that the compiler writers are the same way, though: '/' gets you the
'quotient' from the machines native 'integer divide' instructions, '%' gets you
the 'remainder' from that instruction.  Pleas that they are just perpetuating
the mathematical unsophistication of the hardware designers fall on deaf ears.

The heart of the misunderstanding is that some folk seem to beliave that a
proper 'invariant' for the mod function should be:
     ((-1)*a) mod M  = -1 * (a mod M).
This is INCORRECT!!!  The proper invariant (as any mathematician will tell you)
is that
    a mod M = (a - M) mod M = (a + M) mod M
Notice that this latter invariant is violated by most of the dumb-remainder
implementations.

I've mostly given up: I brute-force make my numbers all be postive (saving the
signs away), do '/' or '%' (which is usually predictable and correct for
all-positive operands), and then do a 'switch' to tune things depending on what
the signs used to be.

  /bernie



More information about the Comp.lang.c mailing list