rule for promotion

Discussion in 'C Programming' started by pembed2003, Apr 15, 2004.

  1. pembed2003

    pembed2003 Guest

    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!
     
    pembed2003, Apr 15, 2004
    #1
    1. Advertising

  2. pembed2003

    Malcolm Guest

    "pembed2003" <> 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.
     
    Malcolm, Apr 15, 2004
    #2
    1. Advertising

  3. In article <c5mmnc$68g$>,
    "Malcolm" <> wrote:

    > "pembed2003" <> 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.
     
    Christian Bau, Apr 15, 2004
    #3
  4. pembed2003

    pembed2003 Guest

    Christian Bau <> wrote in message news:<>...
    > In article <c5mmnc$68g$>,
    > "Malcolm" <> wrote:
    >
    > > "pembed2003" <> 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!
     
    pembed2003, Apr 16, 2004
    #4
  5. On Fri, 15 Apr 2004, pembed2003 wrote:
    >
    > Christian Bau <> 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
     
    Arthur J. O'Dwyer, Apr 16, 2004
    #5
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jon Paul Jones

    ASP.NET, source safe and promotion levels

    Jon Paul Jones, Jan 19, 2005, in forum: ASP .Net
    Replies:
    8
    Views:
    427
    Rusty Zarse
    Feb 8, 2005
  2. =?Utf-8?B?TWlrZSBNb29yZQ==?=

    Code Promotion

    =?Utf-8?B?TWlrZSBNb29yZQ==?=, Apr 10, 2006, in forum: ASP .Net
    Replies:
    1
    Views:
    488
    OHM \( One Handed Man \)
    Apr 10, 2006
  3. Chris
    Replies:
    8
    Views:
    2,593
    Michael Borgwardt
    Sep 4, 2004
  4. Replies:
    5
    Views:
    406
    Jonathan N. Little
    Feb 18, 2006
  5. Replies:
    0
    Views:
    1,403
Loading...

Share This Page