I want to generate million of random numbers between 0 and 1 (0 and 1 included) using thread on POSIX. I try two codes but it still give me wrong results, it generate large signed numbers.
code(1):
srand(time(NULL));
for (i = 0; i < 10; i++)
{
double r = (double)(rand()%1001)/1000;
printf("Random double, 0 to 1: %f\n",r);
}
code(2):
srand(time(NULL));
for (i = 0; i < 10; i++)
{
double r = rand()/(double)RAND_MAX;
printf("Random double, 0 to 1: %f\n",r);
}
The results generated are like these:
12451421454
-4514251445
96541213212
-56543214521
SO what is the solution ,,,, please
Right ! The computed value of pi is not precise.
If you have 30 min, look at this video about generation of random number. Or this question C++ random float number generation.
x=(double)(rand()%1001)/1000; is not the right way to generate random numbers between 0 and 1...There are only 1000 possible values and some are more probable than others since RAND_MAX%1001!=0! x = rand()/(double)RAND_MAX; works better.
Moreover, remember the central limit theorem : the error goes like 1/sqrt(total) : you will never get 10 digits. Try to increase total.
And sqrt(x*x+y*y)<1 is costly : (x*x+y*y)<1 is sufficient.
Ultimately, try random of C++11.
srand(time(NULL)); may be a cause of trouble if you plan to use many threads : time(NULL) only changes once in a second, and many threads will get the same value. Send a seed to the thread or use a random_device to seed your random generator.
Related
I am trying to simulate the propagation of a worm across a network made of 100,000 computers. The simulation itself is very simple and I don't need any help except that for some reason, I am only getting every third random number.
Only the computers whose index modulo 1000 is less than 10 can be infected so when 1000 computers are infected, the program should be done. For some reason, my program only gets 329. When I lower the goal number and check the contents of the array, only every third computer has been changed and it is a consistent pattern. For example at the end of the array, only computers 98001, 98004, 98007, 99002, 99005, 99008 are changed even though the computers in between (98002, 98003, etc.) should be changed as well. The pattern holds all the way to the beginning of the array. When I try to get all 1000 changed, the program goes into an infinite loop and is stuck at 329.
Edit: I just discovered that if I lower the NETSIZE to 10,000 and the goal in the while loop to 100, it doesn't skip anything. Does that mean the problem has something to do with a rounding error? Someone who knows more about C than me must know the answer.
Thanks.
#include <stdio.h>
#include <stdlib.h>
#define NETSIZE 100000
double rand01();
void initNetwork();
unsigned char network[NETSIZE];
int scanrate = 3;
int infectedCount;
int scans;
int ind;
int time;
int main(void) {
initNetwork();
time = 0;
infectedCount = 1;
while (infectedCount < 1000) { //changing 1000 to 329 stops the infinite loop
scans = infectedCount * scanrate;
for (int j = 0; j < scans; j++) {
ind = (int) (rand01() * NETSIZE);
if (network[ind] == 0) {
network[ind] = 1;
infectedCount++;
}
}
time++;
}
for (int k = 0; k < NETSIZE; k++) {
if (network[k] == 1) printf("%d at %d\n", network[k], k);
}
}
double rand01() {
double temp;
temp = (rand() + 0.1) / (RAND_MAX + 1.0);
return temp;
}
void initNetwork() {
for (int i = 0; i < NETSIZE; i++) {
if (i % 1000 < 10) {
network[i] = 0;
} else {
network[i] = 2;
}
}
network[1000] = 1;
}
In the above code, I expect the code to run until the 1000 vulnerable indexes are changed from 0 to 1.
Converting comments into an answer.
What is RAND_MAX on your system? If it is a 15-bit or 16-bit value, you probably aren't getting good enough quantization when converted to double. If it is a 31-bit or bigger number, that (probably) won't be the issue. You need to investigate what values are generated by just the rand01() function with different seeds, plus the multiplication and cast to integer — simply print the results and sort -n | uniq -c to see how uniform the results are.
On my system RAND_MAX is only 32767. Do you think that might be why my results might not be granular enough? Now that you've made me think about it, there would only be 32,767 possible values and my network array is 100,000 possible values. Which corresponds about about the 1/3 results I am getting.
Yes, I think that is very probably the problem. You want 100,000 different values, but your random number generator can only generate about 33,000 different values, which is awfully close to your 1:3 metric. It also explains immediately why you got good results when you reduced the multiplier from 100,000 to 10,000.
You could try:
double rand01(void)
{
assert(RAND_MAX == 32767);
return ((rand() << 15) + rand()) / ((RAND_MAX + 1.0) * (RAND_MAX + 1.0));
}
Or you could use an alternative random number generator — for example, POSIX defines both the drand48() family of functions and
random(), with corresponding seed-setting functions where needed.
Yeah, the problem I am having is that the RAND_MAX value on my system is only 32767 and I am trying to effectively spread that out over 100,000 values which results in about only every third number ever showing up.
In my defense, the person who suggested the rand01() function has a PhD in Computer Science, but I think he ran this code on our school's main computer which probably has a much bigger RAND_MAX value.
#JonathanLeffler deserves credit for this solution.
The problem I am given is the following:
Write a program to discover the answer to this puzzle:"Let's say men and women are paid equally (from the same uniform distribution). If women date randomly and marry the first man with a higher salary, what fraction of the population will get married?"
From this site
My issue is that it seems that the percent married figure I am getting is wrong. Another poster asked this same question on the programmers exchange before, and the percentage getting married should be ~68%. However, I am getting closer to 75% (with a lot of variance). If anyone can take a look and let me know where I went wrong, I would be very grateful.
I realize, looking at the other question that was on the programmers exchange, that this is not the most efficient way to solve the problem. However, I would like to solve the problem in this manner before using more efficient approaches.
My code is below, the bulk of the problem is "solved" in the test function:
#include <cs50.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ARRAY_SIZE 100
#define MARRIED 1
#define SINGLE 0
#define MAX_SALARY 1000000
bool arrayContains(int* array, int val);
int test();
int main()
{
printf("Trial count: ");
int trials = GetInt();
int sum = 0;
for(int i = 0; i < trials; i++)
{
sum += test();
}
int average = (sum/trials) * 100;
printf("Approximately %d %% of the population will get married\n", average / ARRAY_SIZE);
}
int test()
{
srand(time(NULL));
int femArray[ARRAY_SIZE][2];
int maleArray[ARRAY_SIZE][2];
// load up random numbers
for (int i = 0; i < ARRAY_SIZE; i++)
{
femArray[i][0] = (rand() % MAX_SALARY);
femArray[i][1] = SINGLE;
maleArray[i][0] = (rand() % MAX_SALARY);
maleArray[i][1] = SINGLE;
}
srand(time(NULL));
int singleFemales = 0;
for (int k = 0; k < ARRAY_SIZE; k++)
{
int searches = 0; // count the unsuccessful matches
int checkedMates[ARRAY_SIZE] = {[0 ... ARRAY_SIZE - 1] = ARRAY_SIZE + 1};
while(true)
{
// ARRAY_SIZE - k is number of available people, subtract searches for people left
// checked all possible mates
if(((ARRAY_SIZE - k) - searches) == 0)
{
singleFemales++;
break;
}
int randMale = rand() % ARRAY_SIZE; // find a random male
while(arrayContains(checkedMates, randMale)) // ensure that the male was not checked earlier
{
randMale = rand() % ARRAY_SIZE;
}
checkedMates[searches] = randMale;
// male has a greater income and is single
if((femArray[k][0] < maleArray[randMale][0]) && (maleArray[randMale][1] == SINGLE))
{
femArray[k][1] = MARRIED;
maleArray[randMale][1] = MARRIED;
break;
}
else
{
searches++;
continue;
}
}
}
return ARRAY_SIZE - singleFemales;
}
bool arrayContains(int* array, int val)
{
for(int i = 0; i < ARRAY_SIZE; i++)
{
if (array[i] == val)
return true;
}
return false;
}
In the first place, there is some ambiguity in the problem as to what it means for the women to "date randomly". There are at least two plausible interpretations:
You cycle through the unmarried women, with each one randomly drawing one of the unmarried men and deciding, based on salary, whether to marry. On each pass through the available women, this probably results in some available men being dated by multiple women, and others being dated by none.
You divide each trial into rounds. In each round, you randomly shuffle the unmarried men among the unmarried women, so that each unmarried man dates exactly one unmarried woman.
In either case, you must repeat the matching until there are no more matches possible, which occurs when the maximum salary among eligible men is less than or equal to the minimum salary among eligible women.
In my tests, the two interpretations produced slightly different statistics: about 69.5% married using interpretation 1, and about 67.6% using interpretation 2. 100 trials of 100 potential couples each was enough to produce fairly low variance between runs. In the common (non-statistical) sense of the term, for example, the results from one set of 10 runs varied between 67.13% and 68.27%.
You appear not to take either of those interpretations, however. If I'm reading your code correctly, you go through the women exactly once, and for each one you keep drawing random men until either you find one that that woman can marry or you have tested every one. It should be clear that this yields a greater chance for women early in the list to be married, and that order-based bias will at minimum increase the variance of your results. I find it plausible that it also exerts a net bias toward more marriages, but I don't have a good argument in support.
Additionally, as I wrote in comments, you introduce some bias through the way you select random integers. The rand() function returns an int between 0 and RAND_MAX, inclusive, for RAND_MAX + 1 possible values. For the sake of argument, let's suppose those values are uniformly distributed over that range. If you use the % operator to shrink the range of the result to N possible values, then that result is still uniformly distributed only if N evenly divides RAND_MAX + 1, because otherwise more rand() results map to some values than map to others. In fact, this applies to any strictly mathematical transformation you might think of to narrow the range of the rand() results.
For the salaries, I don't see why you even bother to map them to a restricted range. RAND_MAX is as good a maximum salary as any other; the statistics gleaned from the simulation don't depend on the range of salaries; but only on their uniform distribution.
For selecting random indices into your arrays, however, either for drawing men or for shuffling, you do need a restricted range, so you do need to take care. The best way to reduce bias in this case is to force the random numbers drawn to come from a range that is evenly divisible by the number of options by re-drawing as many times as necessary to ensure it:
/*
* Returns a random `int` in the half-open interval [0, upper_bound).
* upper_bound must be positive, and should not exceed RAND_MAX + 1.
*/
int random_draw(int upper_bound) {
/* integer division truncates the remainder: */
int rand_bound = (RAND_MAX / upper_bound) * upper_bound;
for (;;) {
int r = rand();
if (r < rand_bound) {
return r % upper_bound;
}
}
}
I came across rgba's floating point random number generator:
http://rgba.org/articles/sfrand/sfrand.htm
The explanation is clear and the code is simple. There is one issue: I cannot figure out where the random bits come from. Code snippet below:
static unsigned int mirand = 1;
float sfrand( void )
{
unsigned int a;
mirand *= 16807;
a = (mirand&0x007fffff) | 0x40000000;
return( *((float*)&a) - 3.0f );
}
I did try to compile this function and always get a result of -0.995993, which makes sense if mirand starts out as 1. What am I missing, or is mirand simply the seed?
Truth is, that code does NOT generate random numbers... it generates pseudo-random numbers. Assuming you start with the same seed, a layman's way to imagine what's happening is that you are just going through a HUGE list of "random" numbers. Eventually, the numbers will repeat themselves, but a good formula is one that makes this repetition happen at a large interval.
To clarify, take a look at the rand formula that Excel uses: http://support.microsoft.com/kb/828795
The reason you're getting the same number every time is because this is in fact a pseudo random number generator just like regular ones. It has no seed so you will always get the same value on the nth call. If you make several subsequent calls to sfrand you'll see the results, which are uniform between -1 and 1:
-0.995993
0.347347
-0.130602
0.970146
-0.749159
0.883045
Just like if you were to call the normal rand() function without seeding it you'd see the same sequence. As discussed the number 16807 was chosen for good reason, so you can seed this number by calling the function a random number of times:
static unsigned int mirand = 1;
float sfrand(double seed)
{
unsigned int a;
mirand *= seed;
a = (mirand&0x007fffff) | 0x40000000;
return( *((float*)&a) - 3.0f );
}
int main()
{
srand(time(NULL));
int count = rand() % 1000 + 1
for(int i = 0; i < count; ++i)
sfrand();
}
This will just discard the first count values while still giving you a random seed, and all subsequent calls will still gain the performance boost intended by the function. Subsequent calls now return unique values:
codys-macbook-pro:~ cody$ ./a.out
0.166836
codys-macbook-pro:~ cody$ ./a.out
0.256372
codys-macbook-pro:~ cody$ ./a.out
-0.194259
codys-macbook-pro:~ cody$ ./a.out
-0.556834
I use this function to create random numbers between 100000000 and 999999999
int irand(int start, int stop) {
double range = stop - start + 1;
return start + (int)(range * rand()/(RAND_MAX+1.0));
}
When I use it like this, it's properly working
while(1) {
DWORD dw = irand(100000000, 999999999);
printf("dynamic key: %d\n", dw);
Sleep(100);
}
But when I use this function without the while(1), I always get the same number.
What do I need to fix?
The random number generator must be seeded with some source of entropy for you to see different sequences each time, otherwise an initial seed value of 1 is used by the rand function. In your case, calling srand (time(NULL)); once before the irand function is first called should do the trick. You might find this question useful: why do i always get the same sequence of random numbers with rand() ?
Not a direct answer to your question, but something you should probably read if you're struggling with random numbers. This recent article by our very own Jon Skeet is a good intro to random numbers and the trubles one might run into: http://csharpindepth.com/Articles/Chapter12/Random.aspx
gcc 4.4.4 c89
I am using the code below. However, I keep getting the same number:
size_t i = 0;
for(i = 0; i < 3; i++) {
/* Initialize random number */
srand((unsigned int)time(NULL));
/* Added random number (simulate seconds) */
add((rand() % 30) + 1);
}
I would like to get 0 to 30 returned. However, the last time I ran this I got 17 three times.
Many thanks,
You're seeding inside the loop (with the same value because of how quickly the loop will be executed), which causes the random number generated to be the same each time.
You need to move your seed function outside the loop:
/* Initialize random number */
srand((unsigned int)time(NULL));
for(i = 0; i < 3; i++) {
/* Added random number (simulate seconds) */
add((rand() % 30) + 1);
}
You need to call srand just once, at the beginning of your program.
srand initializes the pseudo random number generator using time in seconds. If you initialize it with a particular number, you will always get the same sequence of numbers. That's why you usually want to initialize it at the beginning using the time (so that the seed is different each time you run the program) and then use only rand to generate numbers which seem random.
In your case the time does not change from iteration to iteration, as its resolution is just 1 second, so you are always getting the first number of the pseudo-random sequence, which is always the same.
You need to do srand((unsigned int)time(NULL)) only once before the loop.
It is completely possible that the 3 times 17 are still completely random.
There is an about 1 in 10 chance of getting two numbers the same when using a range of 1-30 and three picks. (this is due to the birthday problem )
Now, getting three the same results has still a propability of 1 in 900 using the same range.
you might want to read more background on the analysis page of random.org
Seed to the pseudo Random number generator should be called only once outside the loop. Using time as a seed is good thing.
However there is still a possiblity of getting the same random number.
I rather suggest also using gettimeofday() system call to retrieve the seed to be used to feed srand().
Something like
struct timeval tv;
...
gettimeofday(&tv, NULL);
srand(tv.tv_usec);
...
This approach can add more entropy in your pseudo number generation code.
IMHO of course
Ciao ciao