[comp.lang.c] /, >>, %, and other ugliness...

sbigham@dukeac.UUCP (Scott Bigham) (11/05/88)

In article <11529@bellcore.bellcore.com> sjs@ctt.bellcore.com (Stan Switzer) writes:
>Well, I really hate to open this can of worms yet again, but in my
>experience whenever (for integer i) "i%4" and "i>>2" differ...

Errr... in my experience, i%4 and i>>2 will almost always differ.  They're
not even doing the same thing.

>, what you
>REALLY want is what "i>>2" does anyway (assuming 2's complement).

I'll assume (possibly incorrectly) that you meant i/4 when you said i%4
and answer below.

>Which is to say that you want the MODULUS operation rather than the
>REMAINDER operation.

Errr... The modulus operation IS the remainder operation.

>  I have seen MANY cases where this is true, and
>have NEVER seen a case where it was false.

(See my assumption above) Consider:

double r;
int i=5;
.
.
.
 r=i/4;

What I want is not what i>>2 does, nor, for that matter, what i/4 does.
What I want is what i/4 -should- do; ie. return r=1.25.  Yes, I know I can 
say r=(double)(i/4).  The irony here is that C can't make this simple
conversion, and yet will gladly convert a char * into a FILE * when I don't
even want it to.

>The PC/RT implements ... i%n to always
>return a value (0..n-1) for positive "n" (dunno about negative "n").

Then you're lucky.  All the C's I've ever used thought (-1)%5==-1.

>Please, do not argue that integer -1/2 should be -1 so that the sign
>is the same as -1.0/2.0 or because "by the laws of arithmetic" (-1)/2
>equals -(1/2).  These are pointless arguments that have no useful
>consequences as far as correct programs are concerned.

By definition, the greatest integer of x is the largest integer n such
that n<=x; then integer -1/2 is -1.  Do programs that use correct
math not count as correct programs?

>Anyone wishing to take up the other side of the argument must find an
>example of an actual situation where having -1/2 yield -1 is useful.

Actually, I'd MUCH rather have -1/2 yield -0.5...

>1) [0..3] represents [north, east, south, and west].  With the modular
>% operator, "dir = (dir-1)%4" means "turn left".  I first came across
>this in a program that drew Hilbert curves.

Be careful; as I mentioned above, some C's don't get this right.  This has
bitten me several times.

>2) Bit extraction:  To get the n'th bit from the current (char) pointer
>"p" (0 bit is low) use "bit = (p[i/BITSPERCHAR]>>(i%BITSPERCHAR)) & 1"
>This comes up in rasterization code often enough.  The usual solution
>is to jimmy it so that you avoid negative "i" (or just use >>3 and &7
>instead).

Yes, if you're doing bit manipulation, then bitwise operations are the natural
choice.  If you're doing arithmetic, than arithmetic operations are the
natural choice.

>You should never have to code "i>>3" when you mean "i/8".

Exactly.  At least three people have said this already.  If you mean i/8,
-say- i/8.

>  You should
>also never have to worry that a 45 cycle divide instruction is going
>to be used so that in case the quotient is negative you'll get the
>answer that someone thought you wanted instead of the one you probably
>really want anyway...

Errr... when I say i/-4, I want i/-4.  You seem to think I want something
different.

>Stan Switzer  sjs@ctt.bellcore.com

						sbigham
-- 
Scott Bigham                         "The opinions expressed above represent
Internet sbigham@dukeac.ac.duke.edu   me and everyone that agrees with me.
USENET   sbigham@dukeac.UUCP          If that includes Duke University,
...!mcnc!ecsgate!dukeac!sbigham       I'll be amazed."

mouse@mcgill-vision.UUCP (der Mouse) (11/15/88)

In article <1081@dukeac.UUCP>, sbigham@dukeac.UUCP (Scott Bigham) writes:
> In article <11529@bellcore.bellcore.com> sjs@ctt.bellcore.com (Stan Switzer) writes:
>> Which is to say that you want the MODULUS operation rather than the
>> REMAINDER operation.
> Errr... The modulus operation IS the remainder operation.

The range of i MOD n is [0,n); the range of i REM n depends on the
division operation in use, since REM is the operation such that
(i REM n) + n * (i DIV n) == i
This usually means the range of i REM n is (-n,n), not [0,n), since DIV
usually truncates towards zero rather than either infinity.  C defines
/ and % (for integer operands) to be DIV and REM in my terminology
above.  Having all three flavors of DIV/REM behavior available would be
nice, though it could rapidly get confusing.

> Consider:
> double r;
> int i=5;
> ...
>  r=i/4;

> What I want is what i/4 -should- do; ie. return r=1.25.  Yes, I know
> I can say r=(double)(i/4).

And get 1.0, same as for r=i/4.  Perhaps you meant r=i/4.0 or
r=(double)i/4 instead?

In what sense "should" i/4 produce 1.25 instead of 1?  It may be what
*you* want, but it isn't C.

> The irony here is that C can't make this simple conversion,

Sure it can.  All you have to do is ask it to.  You seem to expect it
to read your mind and somehow realize that you want it to, without your
having to tell it so.

					der Mouse

			old: mcgill-vision!mouse
			new: mouse@larry.mcrcim.mcgill.edu

desnoyer@Apple.COM (Peter Desnoyers) (11/16/88)

In article <1351@mcgill-vision.UUCP> mouse@mcgill-vision.UUCP (der Mouse) writes:
>In article <1081@dukeac.UUCP>, sbigham@dukeac.UUCP (Scott Bigham) writes:
>> In article <11529@bellcore.bellcore.com> sjs@ctt.bellcore.com (Stan Switzer) writes:
>>> Which is to say that you want the MODULUS operation rather than the
>>> REMAINDER operation.
>> Errr... The modulus operation IS the remainder operation.
>
>The range of i MOD n is [0,n); the range of i REM n depends on the
>division operation in use, since REM is the operation such that
>(i REM n) + n * (i DIV n) == i

[forgive me if my algebra is shaky - it's been years...]

Actually, i MOD n maps Z onto Zn, where Zn is the group {integers
modulo n}. The _canonical_ representation of Zn is {0..n-1} - but it
is not the only one. (e.g. {0,1} === {-1,0}) What is braindead is
taking an operation that maps Z -> Z(2n) and calling it MODULO n. 

				Peter Desnoyers