Reputation: 41
This code has generated a 1 result for r on the 1st toss 200 times in a row; the later tosses aren't static; they change; any idea what I screwed up?? Using Xcode. Thanks!
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define tprop .5 // propability coin will be tails
int main(int argc, const char *argv[])
{
int i; // for loop counter
int n; // # of rolls
int hc = 0; // heads counter
int tc = 0; // tails counter
int r; // roll... 1=heads, 0=tails
srand(time(NULL)); // seed Random# generator with current time
printf("Enter # of times to toss a coin: ");
scanf("%i", &n);
for (i = 0; i < n; i++) {
if ((float) rand() / RAND_MAX > tprop) {
r = 1;
hc++;
} else {
r = 0;
tc++;
}
printf("%in", r);
}
printf("# of times heads came up: %i (%f%%)n", hc, (float) hc / n * 100);
printf("# of times tails came up: %i (%f%%)n", tc, (float) tc / n * 100);
return 0;
}
Upvotes: 3
Views: 907
Reputation: 420
The Windows (here simulated with wine) and glibc (x86_64) version of rand are completely different, but the code will compile either place. Your code works great on my Linux box, but today, at this hour, Windows version of your code always returns 1 for me on the first roll when using seeds generated from time(NULL)--even if I wait a few minutes. Maybe some hours, days, months down the road that will be different. Check this out:
#include <stdio.h>
#include <stdlib.h>
int main (int argc, const char *argv[]) {
int i;
int r;
printf ("rand() returns:\n",RAND_MAX);
for (i = 0; i < 25; i++) {
srand (i);
r = rand();
printf ("%i ", r);
} printf ("\nout of RAND_MAX of %li\n",RAND_MAX);
return 0;
}
Result on Linux (x86_64):
rand() returns:
1804289383 1804289383 1505335290 1205554746 1968078301 590011675 290852541 1045618677 757547896 444454915 1215069295 1989311423 1687063760 1358590890 2146406683 762299093 462648444 1227918265 1995168598 623271449 319571911 1086411056 1857631170 1562469902 188364873
out of RAND_MAX of 2147483647
Result on wine (compiled with mingw):
rand() returns:
38 41 45 48 51 54 58 61 64 68 71 74 77 81 84 87 90 94 97 100 103 107 110 113 116
out of RAND_MAX of 32767
Note how the windows version is more tightly-coupled to the seed value, so it returns really low results compared to RAND_MAX of 32767.
Upvotes: 3
Reputation: 4952
To answer this question, first we need to look at rand() code.
From Rand Implementation:
void __cdecl srand (unsigned int seed)
{
#ifdef _MT
_getptd()->_holdrand = (unsigned long)seed;
#else /* _MT */
holdrand = (long)seed;
#endif /* _MT */
}
int __cdecl rand (void)
{
#ifdef _MT
_ptiddata ptd = _getptd();
return( ((ptd->_holdrand = ptd->_holdrand * 214013L + 2531011L) >> 16) &
0x7fff );
#else /* _MT */
return(((holdrand = holdrand * 214013L + 2531011L) >> 16) & 0x7fff);
#endif /* _MT */
}
As you can see, the random value is computed based on the seed value (and a new seed value is the computed), thats why we call those numbers pseudo-random. Since we are intersted in the first run, lets simplify the code a bit, lets write a function which takes the input the seed, and return the first rand():
int firstRand(unsigned int seed) {
return (((seed * 214013L + 2531011L) >> 16) & 0x7fff);
}
And now lets run a test with with this function:
for (i = 0; i < 50; ++i) {
printf("seed = %u; rand = %d\n", seed + i, firstRand(seed + i));
}
Here I got this result:
seed = 1333783311; rand = 19779
seed = 1333783312; rand = 19783
seed = 1333783313; rand = 19786
seed = 1333783314; rand = 19789
seed = 1333783315; rand = 19792
seed = 1333783316; rand = 19796
seed = 1333783317; rand = 19799
seed = 1333783318; rand = 19802
seed = 1333783319; rand = 19805
seed = 1333783320; rand = 19809
seed = 1333783321; rand = 19812
seed = 1333783322; rand = 19815
seed = 1333783323; rand = 19819
seed = 1333783324; rand = 19822
seed = 1333783325; rand = 19825
seed = 1333783326; rand = 19828
seed = 1333783327; rand = 19832
seed = 1333783328; rand = 19835
seed = 1333783329; rand = 19838
seed = 1333783330; rand = 19841
seed = 1333783331; rand = 19845
seed = 1333783332; rand = 19848
seed = 1333783333; rand = 19851
seed = 1333783334; rand = 19854
seed = 1333783335; rand = 19858
seed = 1333783336; rand = 19861
seed = 1333783337; rand = 19864
seed = 1333783338; rand = 19868
seed = 1333783339; rand = 19871
seed = 1333783340; rand = 19874
seed = 1333783341; rand = 19877
seed = 1333783342; rand = 19881
seed = 1333783343; rand = 19884
seed = 1333783344; rand = 19887
seed = 1333783345; rand = 19890
seed = 1333783346; rand = 19894
seed = 1333783347; rand = 19897
seed = 1333783348; rand = 19900
seed = 1333783349; rand = 19903
seed = 1333783350; rand = 19907
seed = 1333783351; rand = 19910
seed = 1333783352; rand = 19913
seed = 1333783353; rand = 19917
seed = 1333783354; rand = 19920
seed = 1333783355; rand = 19923
seed = 1333783356; rand = 19926
seed = 1333783357; rand = 19930
seed = 1333783358; rand = 19933
seed = 1333783359; rand = 19936
seed = 1333783360; rand = 19939
So, as you can see, if the seed are close, the values will probably be close to, and since you used the current time, the 200 tests you ran were all with seed values close to each other.
time(NULL) return the current time in seconds. To get better results you should use the time in milliseconds (and if you really need the values to change a lot between 2 runs do some operation over it).
Upvotes: 4
Reputation: 26022
Probably your tests are scripted and run as fast as you could run them.
So most tests will be executed within the same wall time second.
You seed the pseudo-random number generator with the current timestamp, which has a resolution of one second.
You can look into other entropy sources like /dev/urandom/
on Linux or BSDs.
If you run your code on a x86/x64 system, you could use the time stamp counter as a entropy source, too.
Upvotes: 1