Velocity Reviews > rule for promotion

# rule for promotion

pembed2003
Guest
Posts: n/a

 04-15-2004
Hi All,
I hope I am posting a C question instead of a C++ this time. I have
the following program:

#include<stdlib.h>
#include<stdio.h>
#include<math.h>
#include<time.h>

int main(int argc,char** argv){
int i;
srand(time(0));
for(i = 0; i < 20; i++){
int x = 1 + (int) (20.0 * rand() / (RAND_MAX + 1.0));
int y = 1 + (int) (20 * rand() / (RAND_MAX + 1.0));
int z = 1 + (int) (20.0 * rand() / (RAND_MAX + 1 ));
printf("%d %d %d\n",x,y,z);
}
}

and it prints:

12 1 -18
4 1 -17
14 1 -12
17 1 -13
8 1 0
9 1 -2
.... etc

it looks like x is always between 1 and 20. y is always 1 and z is
always between negative and 0. i don't understand why. i guess i
understand why x is always positive because the whole expression is
evaluated in long(?) so there won't be any overflow, right? But is y
and z behave so differently? I though C promote the expression if one
of them is long instead of int, right? Can someone explain what
happened? Thanks!

Malcolm
Guest
Posts: n/a

 04-15-2004

"pembed2003" <(E-Mail Removed)> wrote in message
>
> int z = 1 + (int) (20.0 * rand() / (RAND_MAX + 1 ));
> it looks like x is always between 1 and 20. y is always 1 and z is
> always between negative and 0. i don't understand why.
>

The expression rand() / (RAND_MAX + 1) will be evaluated first as an integer
expression. RAND_MAX on your machine must equal INT_MAX, so RAND_MAX + 1 is
the lowest possible negative integer.

Christian Bau
Guest
Posts: n/a

 04-15-2004
In article <c5mmnc\$68g\$(E-Mail Removed)>,
"Malcolm" <(E-Mail Removed)> wrote:

> "pembed2003" <(E-Mail Removed)> wrote in message
> >
> > int z = 1 + (int) (20.0 * rand() / (RAND_MAX + 1 ));
> > it looks like x is always between 1 and 20. y is always 1 and z is
> > always between negative and 0. i don't understand why.
> >

> The expression rand() / (RAND_MAX + 1) will be evaluated first as an integer
> expression. RAND_MAX on your machine must equal INT_MAX, so RAND_MAX + 1 is
> the lowest possible negative integer.

You should really know that this is not true.

20.0 * rand() / (RAND_MAX + 1) is evaluated as follows:

20.0 => Value 20, type double.
rand () => Random value, type int, from 0 to RAND_MAX
(RAND_MAX + 1) => Type int. If RAND_MAX == INT_MAX then -> overflow,
undefined behavior; many implementations will produce INT_MIN.

20.0 * rand () => rand () is converted to double, result is of type
double, from 0 to 20 * RAND_MAX.
20.0 * rand () / (RAND_MAX + 1) => RAND_MAX + 1 is converted to
double. If there was no overflow in calculating RAND_MAX + 1 then the
result is of type double, >= 0.0 and < 20.0. If there is an overflow,
then undefined behavior, but most likely the result of (RAND_MAX + 1) is
INT_MIN, which is often - (INT_MAX + 1) = - (RAND_MAX + 1), so the
result is <= 0 and > -20.

pembed2003
Guest
Posts: n/a

 04-16-2004
Christian Bau <(E-Mail Removed)> wrote in message news:<(E-Mail Removed)>...
> In article <c5mmnc\$68g\$(E-Mail Removed)>,
> "Malcolm" <(E-Mail Removed)> wrote:
>
> > "pembed2003" <(E-Mail Removed)> wrote in message
> > >
> > > int z = 1 + (int) (20.0 * rand() / (RAND_MAX + 1 ));
> > > it looks like x is always between 1 and 20. y is always 1 and z is
> > > always between negative and 0. i don't understand why.
> > >

> > The expression rand() / (RAND_MAX + 1) will be evaluated first as an integer
> > expression. RAND_MAX on your machine must equal INT_MAX, so RAND_MAX + 1 is
> > the lowest possible negative integer.

>
> You should really know that this is not true.
>
> 20.0 * rand() / (RAND_MAX + 1) is evaluated as follows:
>
> 20.0 => Value 20, type double.
> rand () => Random value, type int, from 0 to RAND_MAX
> (RAND_MAX + 1) => Type int. If RAND_MAX == INT_MAX then -> overflow,
> undefined behavior; many implementations will produce INT_MIN.
>
> 20.0 * rand () => rand () is converted to double, result is of type
> double, from 0 to 20 * RAND_MAX.
> 20.0 * rand () / (RAND_MAX + 1) => RAND_MAX + 1 is converted to
> double. If there was no overflow in calculating RAND_MAX + 1 then the
> result is of type double, >= 0.0 and < 20.0. If there is an overflow,
> then undefined behavior, but most likely the result of (RAND_MAX + 1) is
> INT_MIN, which is often - (INT_MAX + 1) = - (RAND_MAX + 1), so the
> result is <= 0 and > -20.

Thanks for the explaination. Here is how I look at it:

(20.0 * rand() / (RAND_MAX + 1 ))

If I put parenthesis:

(((20.0) * (rand())) / ((RAND_MAX) + (1)))

so essentially:

(((double) * (int)) / ((int) + (int)))

double * int gives:

((double) / ((int) + (int)))

now since the second expression overflow (in my machine RAND_MAX ==
MAX_INT), we have:

((doubld) / ((MAX_INT) + (1))) = ((double) / (overflow))

which results in a nagetive number. make sense. But I can't understand
why:

(20 * rand() / (RAND_MAX + 1.0))

always result in a 1?

(((20) * (rand())) / ((RAND_MAX) + (1.0)))

so it's:

(((int) * (int)) / ((int) + (double)))

and then:

(((int) * (int)) / (double))

and then from here, I can't understand why it's always a 1. I can
understand that an int * int might overflow but will C promote it to a
double because we have a double just on the right side of /

Thanks!

Arthur J. O'Dwyer
Guest
Posts: n/a

 04-16-2004

On Fri, 15 Apr 2004, pembed2003 wrote:
>
> Christian Bau <(E-Mail Removed)> wrote
> >
> > 20.0 * rand() / (RAND_MAX + 1) is evaluated as follows:
> >
> > 20.0 => Value 20, type double.
> > rand () => Random value, type int, from 0 to RAND_MAX
> > (RAND_MAX + 1) => Type int. If RAND_MAX == INT_MAX then -> overflow,
> > undefined behavior; many implementations will produce INT_MIN.
> >
> > 20.0 * rand () => rand () is converted to double, result is of type
> > double, from 0 to 20 * RAND_MAX.
> > 20.0 * rand () / (RAND_MAX + 1) => RAND_MAX + 1 is converted to
> > double. If there was no overflow in calculating RAND_MAX + 1 then the
> > result is of type double, >= 0.0 and < 20.0. If there is an overflow,
> > then undefined behavior, but most likely the result of (RAND_MAX + 1) is
> > INT_MIN, which is often - (INT_MAX + 1) = - (RAND_MAX + 1), so the
> > result is <= 0 and > -20.

[Why does]

> (20 * rand() / (RAND_MAX + 1.0))
>
> always result in a 1?

It doesn't, of course. It results in a floating-point 'double'
value, on your machine probably between -1.0 and 1.0 (even though of
course technically it could do whatever it liked).
Consider:

20 --> type 'int', value 20
rand() --> type 'int', value 0..RAND_MAX
20 * rand() --> type 'int', value 0..20*RAND_MAX

Now, at this point we realize that RAND_MAX is probably equal to
INT_MAX (as it is on most modern systems); so 20*RAND_MAX overflows
and we have a case of undefined behavior. Let's assume that 'int'
values overflow by "wrapping around," so that the value of 20*rand()
is still a random number between INT_MIN and INT_MAX.

20 * rand() --> type 'int', value INT_MIN..INT_MAX
RAND_MAX + 1.0 --> type 'double', value RAND_MAX+1
whole expression --> type 'double', value...

The value of the whole expression, assuming what we assumed above about
overflow on your machine, is a random number between
(INT_MIN/(RAND_MAX+1.)) and (INT_MAX/(RAND_MAX+1.)) . And since RAND_MAX
is assumed to be INT_MAX, and we can also assume that on your machine
INT_MIN is just -INT_MAX-1, our resulting value is a 'double' value
between -1.0 and INT_MAX/(INT_MAX+1).

> Thanks!

You're welcome.

-Arthur