Thread: random number from interval [0,1]

  1. #1
    Registered User
    Join Date
    Sep 2010
    Location
    Europe
    Posts
    87

    random number from interval [0,1]

    Hello.

    I am a student of C language.

    How can I generate a pseudo-random real number from interval [0,1] ?

    Can it be generalized to any interval? Like [0,a], where 'a' is a parameter?

    I tried searching for it, I only found rand(), srand(), random(1), and randomize. None of it actually seems to work for me..

    Later I actually succeded with something like

    srand( (unsigned)time( NULL ) );
    printf( " %6d\n", rand() );

    but it only produces up to five digits integers and I cannot divide by 99999 to get it into [0,1].

    Thank you.

  2. #2
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    rand() produces a pseudo-random number in the range [0, RAND_MAX]. Thus, you can divide the result of rand() by RAND_MAX and get a float/double value. Note, however, that rand() returns an int, and RAND_MAX is also an int, so simply dividing will result in a value of 0 most of the time, due to integer division, which throws away the decimal portion. Thus, cast one part of it:
    Code:
    double rand_0_1(void)
    {
        return rand() / ((double) RAND_MAX);
    }

  3. #3
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    I agree with anduril462.
    Even on the general formula, we have the same effect. ( I used his comment pretty much and I wrote this)
    Code:
    #include <stdio.h>
    #include <time.h>
    #include <stdlib.h>
    
    /* The division of integers usually gives a
     * result smaller than max                 */
    int randomRange(int min, int max)
    {
        return ( rand() % ( max - min ) ) + min;
    }
    
    int main(void)
    {
        int i=0;
        srand(time(NULL));
        while(i++!=10)
            printf("%d\n", randomRange(0,2));
        return 0;
    }
    Source: Random numbers ∈[min, max]

    EDIT: I admit I am not sure if we can ever get the max as result..
    Last edited by std10093; 02-06-2013 at 06:27 PM.
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

  4. #4
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Quote Originally Posted by std10093 View Post
    EDIT: I admit I am not sure if we can ever get the max as result..
    Yep, just use:
    Code:
    rand() % (max - min + 1) + min;

  5. #5
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    So no. It's like passing as argument max+1. But I get your point
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

  6. #6
    Registered User
    Join Date
    Nov 2012
    Posts
    1,393
    I prefer to define the function so that a number in the range [0,1) is returened.. In other words, numbers as high as 0.9999... will be generated. With this definition, it is straightforward to define randbetween(x,y) in terms of this function.

    Code:
    // return a random double in [0.0, 1.0)
    double randfrac(void) {
        double res = (rand() % RAND_MAX) / (double)RAND_MAX;
        return res;
    }
    
    // return random double in [x,y)
    double randbetween(double x, double y) {
        return randfrac() * (y-x) + x;
    }
    For seeding, you can use time(NULL) but it tends to give a poor seed if you run your program multiple times. I use the tv_usec value from gettimeofday

    Code:
    // call srand(3) using the time value in microseconds
    void doseed(void) {
        struct timeval tp;
        gettimeofday(&tp, NULL);
        unsigned seed = (unsigned)tp.tv_usec;
        srand(seed);
    }
    Then just call doseed() once before calling any random number generating function

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by c99tutorial
    Code:
    // return a random double in [0.0, 1.0)
    double randfrac(void) {
        double res = (rand() % RAND_MAX) / (double)RAND_MAX;
        return res;
    }
     
    // return random double in [x,y)
    double randbetween(double x, double y) {
        return randfrac() * (y-x) + x;
    }
    The method that our fellow forum member Prelude recommended in her article on using rand is:
    Code:
    double uniform_deviate(int seed)
    {
        return seed * (1.0 / (RAND_MAX + 1.0));
    }
    
    int r = M + uniform_deviate(rand()) * (N - M);
    though I do not see why uniform_deviate cannot be simplified to:
    Code:
    double uniform_deviate(int seed)
    {
        return seed / (RAND_MAX + 1.0);
    }
    plus having uniform_deviate take the pseudorandom number as an argument rather than calling rand() directly (in which case it should be renamed, heh) probably is not as flexible as it could be since RAND_MAX is used directly.

    Quote Originally Posted by c99tutorial
    For seeding, you can use time(NULL) but it tends to give a poor seed if you run your program multiple times. I use the tv_usec value from gettimeofday
    In that same article of hers, Prelude suggests hashing the bytes of a time_t, and I like it, especially with her argument that "the C and C++ standards guarantee that type punning is a portable operation for simple types".
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by laserlight View Post
    though I do not see why uniform_deviate cannot be simplified to:
    Code:
    double uniform_deviate(int seed)
    {
        return seed / (RAND_MAX + 1.0);
    }
    Its an optimisation.
    Some compilers, notably Visual Studio, wont make that optimisation when configured a certain way. I believe the /fp:strict option prevents the optimisation because it could produce a result that differs in some of the lower bits between doing only the division vs the multiplication (the division is then done at compile time). And of course in this code it shouldn't matter if the result differed by a tiny amount.

    There is one issue with both though that I haven't thought of before, if RAND_MAX were a 64-bit value then RAND_MAX + 1.0 is not representable as a double. This would affect both bits of code. I'm not sure if any runtimes have RAND_MAX as a 64-bit data type though, or if that's even allowed.
    Last edited by iMalc; 02-06-2013 at 11:12 PM.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  9. #9
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Quote Originally Posted by iMalc View Post
    There is one issue with both though that I haven't thought of before, if RAND_MAX were a 64-bit value then RAND_MAX + 1.0 is not representable as a double. This would affect both bits of code. I'm not sure if any runtimes have RAND_MAX as a 64-bit data type though, or if that's even allowed.
    To be pedantic about the wording, "RAND_MAX + 1.0 might not be representable as a double". That would, of course, depend on what value the implementation gave to RAND_MAX. But that sort of uncertainty generally leads me to code defensively, as though it is definitely not representable as a double. Both the standard and the rationale seem to have little to say about it, though it appears to be implementation defined (within limits):
    Quote Originally Posted by C99 7.20 p3
    The macros defined are...
    RAND_MAX
    which expands to an integer constant expression that is the maximum value returned by
    the rand function;
    Quote Originally Posted by C999 7.20.2.1 p1
    int rand(void);
    Those two give a theoretical upper bound is whatever can fit in an int, since that is what rand() must return. On a 64-bit implementation, that could cause problems computing RAND_MAX + 1.0.
    Quote Originally Posted by C99 7.20.2.1 p5
    The value of the RAND_MAX macro shall be at least 32767.
    That gives a lower bound.

  10. #10
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by iMalc
    There is one issue with both though that I haven't thought of before, if RAND_MAX were a 64-bit value then RAND_MAX + 1.0 is not representable as a double. This would affect both bits of code.
    Good point, but...

    Quote Originally Posted by anduril462
    But that sort of uncertainty generally leads me to code defensively, as though it is definitely not representable as a double.
    I think that if you are concerned about this, then perhaps a (static) assertion for this would work. As far as I can tell, it is not guaranteed that all values in the range of int are representable in the range of double or even long double, hence even a simple cast (without the addition) could be problematic on a given implementation.

    If that is not feasible, I guess another approach is to use the rejection method of reducing the integer range such that you get a range that will be fine for conversion to double.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  11. #11
    Registered User
    Join Date
    Sep 2010
    Location
    Europe
    Posts
    87
    Thank you for replies.

    Quote Originally Posted by c99tutorial View Post
    Code:
    // call srand(3) using the time value in microseconds
    void doseed(void) {
        struct timeval tp;
        gettimeofday(&tp, NULL);
        unsigned seed = (unsigned)tp.tv_usec;
        srand(seed);
    }
    Just here in seeding.. This leads to announcing a error while compiling:

    "In function doseed() storage size of tp isn't known"

    How can I correct it?

  12. #12
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    The struct timeval structure represents an elapsed time. It is declared in sys/time.h and has the following members:

    long int tv_sec
    This represents the number of whole seconds of elapsed time.
    long int tv_usec
    This is the rest of the elapsed time (a fraction of a second), represented as the number of microseconds. It is always less than one million.
    So, if you have not included sys/time.h then you won't know the size of it.
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. need a random number generator thats not compleatly random
    By thedodgeruk in forum C++ Programming
    Replies: 1
    Last Post: 06-05-2011, 06:48 AM
  2. Replies: 5
    Last Post: 10-05-2009, 10:21 AM
  3. Replies: 2
    Last Post: 12-25-2003, 01:31 AM
  4. random number between negative and positive number
    By anomaly in forum C++ Programming
    Replies: 6
    Last Post: 12-06-2003, 08:40 AM
  5. Random Number problem in number guessing game...
    By -leech- in forum Windows Programming
    Replies: 8
    Last Post: 01-15-2002, 05:00 PM