# Thread: Prelude's random numbers tutorial

1. ## Prelude's random numbers tutorial

Why does this code from her tutorial only print out negative numbers? I thought it was supposed to print out numbers between 1-10.
Code:
```#include <iostream>
#include <cstdlib>
#include <ctime>

int main()
{
std::srand ( (unsigned int)std::time ( 0 ) );
std::cout<< (int)( (double)std::rand() / ( RAND_MAX + 1 ) * 10 ) <<std::endl;

return 0;
}```
I don't understand how (double)std::rand() / ( RAND_MAX + 1 ) could ever be a negative number, unless rand() is generating one (which would seem a tad odd). Or maybe it's (RAND_MAX + 1) that is somehow overflowing to -RAND_MAX?

EDIT: It is indeed (RAND_MAX+1) that is overflowing.

2. Originally Posted by ^xor
Or maybe it's (RAND_MAX + 1) that is somehow overflowing to -RAND_MAX?
That's it exactly. I remember seeing that code a while back and thinking it was wrong. It should be:
Code:
`std::cout<< (int)( ((double)std::rand() /  RAND_MAX) * 10 + 1) <<std::endl;`

3. Yeah I kinda figured it out now myself. Maybe someone should modify the tutorial?

4. What compiler, on vc beta express... RAND_MAX IS #DEFINE as 32767 or something close so it's not even coming close to overflowing There is no way that this should output a negative.

5. On Linux with glibc, RAND_MAX is the same size as INT_MAX.

6. Assuming 2-byte integers, it does. I miss 2-byte integers.

7. rand() / RAND_MAX * 10 + 1

In the above expression rand() / RAND_MAX will give a decimal number with a value between 0 and 1 inclusively. Therefore

rand() / RAND_MAX * 10 will give a number between 0 and 10, inclusive and

rand() / RAND_MAX * 10 + 1

will give a number between 1 and 11, inclusive. That's well and good if that is your intention. However (as I remember it) the intention of the original equation

rand() / (RAND_MAX + 1) * 10

was to generate a "random" digit, 0 - 9, inclusive, (and I believe with each value 0-9 being obtained with "equal" frequency given a large sample size). In order to do that, the denominator needs to be at least numerator + 1 for any possible value of the numerator, so the maximal size of the numerator + 1 was chosen as the denominator. That way the ratio is always less than 1 and greater than or equal to zero and the product, when casted to an int, is always 0 - 9. If RAND_MAX is defined as INT_MAX then adding 1 will cause the value to be negative. If it is a simple negation (that is INT_MAX + 1 == -INT_MAX) then you can overcome that by using the absolute value, which is available as abs(). I forget though whether INT_MAX + 1 == -(INT_MAX) or -(INT_MAX - 1).

8. Disclaimer: I haven't read Prelude's tutorial (does anyone have a link?), so I fear I may be working off of false assumptions. Please accept my deepest apologies if that turns out to be the case.

EDIT: It is indeed (RAND_MAX+1) that is overflowing
You could either change it to (RAND_MAX + 1L) to convert to long arithmetic, or even (RAND_MAX + 1U) for unsigned, but a more reliable way of generating random numbers [1...10] is:

Code:
`std::rand() * 9.0 / RAND_MAX + 1;`
However, if the intent was to generate integers [1...10], then this isn't it. The basic idea is to divide up the range of values into 10 "buckets" that the result of rand() will "fall" into. Imagine holding a ball in your hand, and tossing it at the 10 buckets with your eyes closed. Whichever one the ball hits is your number. Simply divide RAND_MAX by 10, and round up for the remainder:

Code:
`const int bucket_size = RAND_MAX / 10 + 1;`
Now, just take the result of rand() divided by bucket_size, and you will have a result [0...9]. All that's left is to add 1 for the offset.

Code:
`int r = std::rand() / bucket_size + 1;`
HTH,
Will

9. Originally Posted by whoie
You could either change it to (RAND_MAX + 1L) to convert to long arithmetic, or even (RAND_MAX + 1U) for unsigned, but a more reliable way of generating random numbers [1...10] is:

Code:
`std::rand() * 9.0 / RAND_MAX + 1;`
That's not a very reliable way at all actually. The only way to generate 10 that way, would be for rand() to generate RAND_MAX. That's a 1/RAND_MAX chance of happening, which is clearly way below the other numbers (1-9).

Your other solution works perfectly though.
Code:
```#include <cstdlib>
#include <ctime>
#include <iostream>

int main(void)
{
unsigned int i;
std::srand((unsigned int)std::time(NULL));
for (i=0; i<50; i++)
std::cout << (int) (std::rand() / (RAND_MAX / 10 + 1)) << std::endl;

return 0;
}```

10. If it is to generate a random number between 0 and n, why not use:
Code:
```std::srand((unsigned int)std::time(NULL));
std::cout << std::rand() % (n+1) << std::endl;```
and
Code:
```std::srand((unsigned int)std::time(NULL));
std::cout << std::rand() % n + 1 << std::endl;```
will generate a number between 1 and n

11. From Prelude's tutorial:
snip... unfortunately the modulo method uses the low order bits of the random number generator. This is bad because poor generators will create non-random sequences when using low order bits for small ranges. The way to improve this is to force the use of high order bits instead by using a value defined in cstdlib called RAND_MAX
There's also a note in the man pages for rand.

12. >(int)( (double)std::rand() / ( RAND_MAX + 1 ) * 10 )
That's a typo, good catch. It came from here:
Code:
`double r0 = (double)rand() / ( RAND_MAX + 1 );`
I was lazy and just cut and pasted without looking. The intention was:
Code:
`(double)rand() / RAND_MAX + 1;`
>maybe it's (RAND_MAX + 1) that is somehow overflowing to -RAND_MAX?
It's RAND_MAX + 1 that's causing undefined behavior. Since RAND_MAX is most likely to be interpreted as a signed integral value, and signed integer overflow is a Bad Thing(tm).

I've been meaning to update all of my tutorials, maybe I should use this as a good reason.

13. That makes it:
Code:
`std::cout<< (int)( (double)std::rand() * 10.0 / RAND_MAX + 1) <<std::endl;`
But that's still not the same as:
Code:
`std::cout << (int) (std::rand() / (RAND_MAX / 10 + 1) + 1) << std::endl;`
The first code generates numbers in the range 1-11 (the 11 only has 1/RAND_MAX of being generated), while the second code generates in the range 1-10 with proper distribution.

14. yep.

15. Originally Posted by whoie
You could either change it to (RAND_MAX + 1L) to convert to long arithmetic, or even (RAND_MAX + 1U) for unsigned, but a more reliable way of generating random numbers [1...10] is:

Code:
std::rand() * 9.0 / RAND_MAX + 1;
Originally Posted by ^xor
That's not a very reliable way at all actually. The only way to generate 10 that way, would be for rand() to generate RAND_MAX. That's a 1/RAND_MAX chance of happening, which is clearly way below the other numbers (1-9).

I'm afraid we misunderstood each other. When I initially wrote that, I wasn't sure if the intent was to generate random integers [1...10] or random "real" numbers. It is obvious now (and should have been at the time with the cast to int that I neglected to notice) that the intent was to generate integers.

But you should look the code above again to see if you really understood what the probability is for all possible results. I think you will find that all results have a 1 / (RAND_MAX + 1) probability. Not just 10.

In hindsight, it was totally irrelevant to the discussion, and I'm sorry for any confusion.

Will