rule for promotion

P

pembed2003

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!
 
M

Malcolm

pembed2003 said:
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.
 
C

Christian Bau

"Malcolm said:
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.
 
P

pembed2003

Christian Bau said:
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!
 
A

Arthur J. O'Dwyer

[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).

You're welcome.

-Arthur
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,571
Members
45,045
Latest member
DRCM

Latest Threads

Top