[comp.sys.mac] Lightspeed C bug?

cnc@hpcilzb.HP.COM (Chris Christensen) (12/23/87)

I have been having a real head-scratcher problem with Lightspeed C.

I am trying to generate random numbers from 0 to 7.

I use

#define ABS(x) (((x) < 0) ? -(x) : (x))
x = ABS(Random()) % 8;

I get random numbers from -7 to 7

I use

x = Random();
x = ABS(x);
x %= 8;

I get the desired range.

This is the define for Absolut that I have always used. Why doesn't this work?
Am I being bitten by a "one pass" compiler bug?

--------------------------------------------------------------------------------
Chris Christensen				Hewlett-Packard
(408) 553-2955 or telnet 553-2955		Design Technology Center
cnc%hpdtc@hplabs.hp.com			Santa Clara, CA
...!hplabs!hpcid!cnc

singer@endor.harvard.edu (Rich Siegel) (12/24/87)

In article <870081@hpcilzb.HP.COM> cnc@hpcilzb.HP.COM (Chris Christensen) writes:
>#define ABS(x) (((x) < 0) ? -(x) : (x))

	This is a macro definition. When you use it, "Random()" is going
to get substituted for  "x" everywhere in this macro. Therefore, "Random()"
will get called twice for any given invocation of this macro.

>x = ABS(Random()) % 8;

	Is not correct.

A correct usage would be:

	x = Random();
	x = ABS(x) % 8;

>Am I being bitten by a "one pass" compiler bug?
	
	Nope.

		--Rich
**The opinions stated herein are my own opinions and do not necessarily
represent the policies or opinions of my employer (THINK Technologies).

* Richard M. Siegel | {decvax, ucbvax, sun}!harvard!endor!singer    *
* Customer Support  | singer@endor.harvard.edu			    *
* Symantec, THINK Technologies Division.  (No snappy quote)         *

jimd@necis.UUCP (Jim Damoulakis) (12/24/87)

In article <870081@hpcilzb.HP.COM> cnc@hpcilzb.HP.COM (Chris Christensen) writes:
>I am trying to generate random numbers from 0 to 7.
>
>I use
>
>#define ABS(x) (((x) < 0) ? -(x) : (x))
>x = ABS(Random()) % 8;
>
>I get random numbers from -7 to 7
>
>I use
>
>x = Random();
>x = ABS(x);
>x %= 8;
>
>I get the desired range.
>
>This is the define for Absolut that I have always used. Why doesn't this work?
>Am I being bitten by a "one pass" compiler bug?
>

It looks like you are confusing a preprocessor operation with a function.
Remember that all preprocessing occurs before compilation.   Therefore your

       ABS(Random()) % 8      is expanded to

       (((Random()) < 0) ? -(Random()) : (Random())) % 8;

which should produce integers between -7 and 7.  

You need to isolate the call to Random() before applying the ABS macro, as
you have done in your second example above.

This looks like normal C behavior to me.  I hope this helps.


Jim Damoulakis               Tel. (617) 263-3833  UUCP: jimd@necis.nec.com
NEC Information Systems, Inc.              289 Great Road, Acton, MA 01720
"It's like deja vu all over again"  -- Yogi Berra
-----------------------------------------------------------------------------
-- 
Jim Damoulakis               Tel. (617) 263-3833  UUCP: jimd@necis.nec.com
NEC Information Systems, Inc.              289 Great Road, Acton, MA 01720
"It's like deja vu all over again"  -- Yogi Berra
-----------------------------------------------------------------------------

lgh@IUS2.CS.CMU.EDU (Leonard Hamey) (12/24/87)

In article <870081@hpcilzb.HP.COM> cnc@hpcilzb.HP.COM (Chris Christensen) writes:
>I have been having a real head-scratcher problem with Lightspeed C.
>
>I am trying to generate random numbers from 0 to 7.
>
>I use
>
>#define ABS(x) (((x) < 0) ? -(x) : (x))
>x = ABS(Random()) % 8;
>
>I get random numbers from -7 to 7
>

Expand the macro and you get....

	x = (((Random()) < 0) ? -(Random ()) : (Random ())

each invocation of Random() generates a NEW random number, so you are
using one random number to determine whether or not to negate another random
number.

I would expect that your best (hack) answer is to use:

	x = Random()&7;

or

	x = Random()&~(-1) % N;
		for randoms on 0..N-1.
----------------------------------------------------------------------
Leonard Hamey			Computer Science Dept.
lgh@cs.cmu.edu			Carnegie Mellon University
<Substitute your favourite disclaimer here>
-- 
----------------------------------------------------------------------
Leonard Hamey			Computer Science Dept.
lgh@cs.cmu.edu			Carnegie Mellon University
<Substitute your favourite disclaimer here>

cnc@hpcilzb.HP.COM (Chris Christensen) (12/25/87)

nevermind. 

ABS(Random()) calls Random twice as someone pointed out.

cnc

dillon@CORY.BERKELEY.EDU (Matt Dillon) (12/25/87)

>I would expect that your best (hack) answer is to use:
>	x = Random()&7;
>or
>	x = Random()&~(-1) % N;
>		for randoms on 0..N-1.

	I think you meant to say (16 bit ints):

	x = (Random()&0x7FFF) % N

	As ~(-1) == 0

				-Matt

dwb@apple.UUCP (David W. Berry) (12/25/87)

In article <870081@hpcilzb.HP.COM> cnc@hpcilzb.HP.COM (Chris Christensen) writes:
>I have been having a real head-scratcher problem with Lightspeed C.
>
>I am trying to generate random numbers from 0 to 7.
>
>I use
>
>#define ABS(x) (((x) < 0) ? -(x) : (x))
>x = ABS(Random()) % 8;
>
>I get random numbers from -7 to 7
>
	Remember that C macros are simple text substitution.  Thus what
the compiler will see (after the preprocessor gets through with it) is:
	x = (((Random()) < 0) ? -(Random()) : (Random())) % 8;
so you're actually calling Random twice for each statement, once to
randomly decide whether or not to negate the value of the second
Random.  This probably isn't what you want :-).

>I use
>
>x = Random();
>x = ABS(x);
>x %= 8;
>
>I get the desired range.
	One would expect it to.  You only call Random one time and then
take the absolute value.  It would also work to use 'x = ABS(x) % 8'
>
>This is the define for Absolut that I have always used. Why doesn't this work?
>Am I being bitten by a "one pass" compiler bug?
	Actually, you're being bitten by a language design feature.
If you're C compiler doesn't do it this way it's a bug.  Remember,
don't call subroutines or do things with side effects inside of
macro usage.  Other things to watch out for are things like:
	while(isalpha(*p++))
which will sometimes do what's expected and sometimes not, and certainly
isn't portable.
>
>--------------------------------------------------------------------------------
>Chris Christensen				Hewlett-Packard
>(408) 553-2955 or telnet 553-2955		Design Technology Center
>cnc%hpdtc@hplabs.hp.com			Santa Clara, CA
>...!hplabs!hpcid!cnc


-- 
	David W. Berry
	dwb@well.uucp                   dwb@Delphi
	dwb@apple.com                   973-5168@408.MaBell
Disclaimer: Apple doesn't even know I have an opinion and certainly
	wouldn't want if they did.

gae@osupyr.UUCP (Gerald Edgar) (12/25/87)

In article <870081@hpcilzb.HP.COM> cnc@hpcilzb.HP.COM (Chris Christensen) writes:
.....
>#define ABS(x) (((x) < 0) ? -(x) : (x))
>x = ABS(Random()) % 8;

The preprocessor converts this to:

 x = (((Random()) < 0) ? -(Random()) : (Random())) % 8;

So that Random() will be evaluated twice.
-- 
  Gerald A. Edgar                               TS1871@OHSTVMA.bitnet
  Department of Mathematics                     gae@osupyr.UUCP
  The Ohio State University  ...{akgua,gatech,ihnp4,ulysses}!cbosgd!osupyr!gae
  Columbus, OH 43210                            70715,1324  CompuServe