# Help with rand()

This is a discussion on Help with rand() within the C Programming forums, part of the General Programming Boards category; I am working on a program that uses rand(). I seed it with Code: srand( (unsigned) time(NULL)) and then do ...

1. ## Help with rand()

I am working on a program that uses rand(). I seed it with
Code:
`srand( (unsigned) time(NULL))`
and then do some arithmetic to scale rand from [0,RAND_MAX] to [-1,1]. I have generated 100,000 random numbers with this and looked at a histogram and everything looked normal. The problem I am running into is when I sum these values. I keep getting a Gaussian not centered on 0. Does anyone have any ideas why this is happening? Is this the result of a bias in the pseudo-random number generator?

More specifically, I am looking at the distribution of 10,000 sums of 100,000 elements ([-1,1]) each and I get a Gaussian centered at -500 every time I run the program. The sample size I am using shouldn't be an issue. Thanks for the help

2. How are you doing the scaling? I note that it is possible to introduce a bias when doing that, and perhaps it matters for what you are trying to do. You might want to post the smallest and simplest runnable program that demonstrates the problem.

3. Yeah you haven't posted the useful bit.
Show us what you're doing, rather than telling us.

4. woops sorry about that. Here is the code with the scaling I am doing:

Code:
```#include <stdio.h>
#include <time.h>
#include <string.h>

FILE * f1;

int main (int argc, const char * argv[]) {
srand( (unsigned) time(NULL));

f1 = fopen("randtest.txt", "w");

for (int j = 0; j < 10000; j++) {
double sum = 0;
for (int i = 0; i < 100000; i++) {
double n = (rand() % 200)/100.00 - 1;
sum += n;

}
fprintf(f1,"%lf\n",sum);
}
return 0;
}```
From a mathematical standpoint I don't see why this would introduce a bias (although I don't do a whole lot of work with mod). I am pretty certain this must be the problem point. Thanks in advance.

5. Originally Posted by waterborne
From a mathematical standpoint I don't see why this would introduce a bias (although I don't do a whole lot of work with mod).
If RAND_MAX+1 is not perfectly divisible by 200 (and this is probably the case), then some of the numbers in the range [0, 200) will have a higher probability of being generated, assuming a uniform distribution for rand().

Still, why not post the smallest and simplest runnable program that demonstrates the problem?

6. Originally Posted by laserlight
If RAND_MAX+1 is not perfectly divisible by 200 (and this is probably the case), then some of the numbers in the range [0, 200) will have a higher probability of being generated, assuming a uniform distribution for rand().

Still, why not post the smallest and simplest runnable program that demonstrates the problem?
That makes sense and I imagine that is what is happening.

The code I posted should run. I run that code and then have a notebook in Mathematica import the data and update a histogram plot.

Do you have a better suggestion for scaling the random number generation to [-1,1]? Thanks!

7. rand() % 200 gives a number from 0 to 199.
Divide that by 100 and you get 0 to 1.99
Subtract 1 and you get -1 to 0.99 (Not -1 to +1)
You probably want mod 201, not 200

8. Originally Posted by waterborne
That makes sense and I imagine that is what is happening.

The code I posted should run. I run that code and then have a notebook in Mathematica import the data and update a histogram plot.

Do you have a better suggestion for scaling the random number generation to [-1,1]? Thanks!
You're getting integers in the range 0 - 199 so the mean will be 99.5, not 100. Divide by 100, subtract 1 and multiply by 100,000 and your mean *should* be -500. You probably want something like this:

Code:
```for (int j = 0; j < 10000; j++) {
double sum = 0;
double frac = 201.0 / (unsigned int)(RAND_MAX + 1);
for (int i = 0; i < 100000; i++) {
double n =  (int)(rand() * frac) / 100.0 - 1;
sum += n;
}
}```

9. Why are you trying to divide by zero?
Code:
`(unsigned int)(RAND_MAX + 1)`
MAX + 1 being unsigned should be zero.

Quzah.

10. Originally Posted by quzah
Why are you trying to divide by zero?
Code:
`(unsigned int)(RAND_MAX + 1)`
MAX + 1 being unsigned should be zero.
I don't think so. rand() returns an int, so RAND_MAX is the largest int that the architecture supports and (unsigned int)(RAND_MAX + 1) is 1 more than that.

But (because of twos-complement) (int)(RAND_MAX + 1) = -(unsigned int)(RAND_MAX + 1).

11. Originally Posted by R.Stiltskin
I don't think so. rand() returns an int, so RAND_MAX is the largest int that the architecture supports and (unsigned int)(RAND_MAX + 1) is 1 more than that.

But (because of twos-complement) (int)(RAND_MAX + 1) = -(unsigned int)(RAND_MAX + 1).
On a system with 32-bit ints, where RAND_MAX is 0xFFFFU it will be fine.
But on a system with 32-bit ints, where RAND_MAX is 0xFFFFFFFFU, it will overflow back to zero, no matter how you look at it.
Note that those are typical values for RAND_MAX, so quzah's point is entirely valid.

12. Originally Posted by iMalc
...But on a system with 32-bit ints, where RAND_MAX is 0xFFFFFFFFU, it will overflow back to zero, no matter how you look at it.
Note that those are typical values for RAND_MAX, so quzah's point is entirely valid.
How can that be? int rand(void) by definition returns an int, not an unsigned int, between 0 and RAND_MAX, so on a system with 32 bit ints RAND_MAX can be no more than 0x7FFFFFFFh, reserving the high-order bit for negative numbers. Add 1 to that and the result overflows to 0x80000000 which is -2147483648d as an int, but cast it to an unsigned int and it is 2147483648d.

edit: but I probably should have written "((unsigned int)RAND_MAX + 1u)" to avoid compiler warnings.

13. Put this in your toolbox:

Code:
```double RandRange( double min, double max )
{
return (double)rand() / RAND_MAX * ( max - min ) + min;
}```

14. Originally Posted by brewbuck

Code:
```double RandRange( double min, double max )
{
return (double)rand() / RAND_MAX * ( max - min ) + min;
}```
Yes, it's much simpler if you want doubles with an arbitrary number of decimal places. That sidesteps the overflow issue nicely, but (judging by his code) the OP seemed to want numbers with exactly 2 decimal places (or equivalently, a range of ints divided by 100.0). This RandRange() doesn't adapt to that so easily (must avoid introducing a bias against the max value).

15. Originally Posted by R.Stiltskin
Yes, it's much simpler if you want doubles with an arbitrary number of decimal places. That sidesteps the overflow issue nicely, but (judging by his code) the OP seemed to want numbers with exactly 2 decimal places.
Then I'd call it like this:

Code:
`double x = round( RandRange( -100.0, 100.0 ) ) / 100.0;`

Page 1 of 2 12 Last