I have written this piece of code which is supposed to simulate throwing dice many many times and counting that how many times each face is up. I have attached the output down there and as you can see it looks kind of strange. For example face 5 comes up exactly 10 times, faces 2, 3, 4 are about the same and face 6 comes zero in two rounds. The only face which acts about normal is 1. Can anyone explain this to me? Is this normal? Am I doing something wrong or is it something related to my system?
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
unsigned long int freq1, freq2, freq3, freq4, freq5, freq6;
unsigned long int L00p = 1;
unsigned short int DF;
while (L00p <= 6e7){
srand (time(NULL));
DF = 1 (rand ()%6);
switch (DF)
{
case 1:
freq1;
break;
case 2:
freq2;
break;
case 3:
freq3;
break;
case 4:
freq4;
break;
case 5:
freq5;
break;
case 6:
freq6;
break;
default:
break;}
L00p;
}
printf ("%s%s\n", "Dice's Face", "Face Frequency");
printf ("1%lu\n", freq1);
printf ("2%lu\n", freq2);
printf ("3%lu\n", freq3);
printf ("4%lu\n", freq4);
printf ("5%lu\n", freq5);
printf ("6%lu\n", freq6);
return 0;
}
and here is the program's output after four times running it:
CodePudding user response:
- You don't initialize the frequency counters, so they'll likely contain garbage from the stack. (So yes, you were getting randomness, but not the randomness you want.)
- You don't want to call
srand()
in the loop, but only once before it. Callingsrand()
with the same number (andtime(NULL)
will quite inevitably return the same second in a tight loop) will reset therand()
generator to return the same sequence of numbers, and since you only ever callrand()
once before callingsrand()
again, you'll get a whole bunch of the same number.
The following version works fine, but you'd have a better time with an array.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
unsigned long int freq1 = 0, freq2 = 0, freq3 = 0, freq4 = 0, freq5 = 0,
freq6 = 0;
srand(time(NULL));
for (int loop = 0; loop < 1000; loop ) {
int DF = 1 (rand() % 6);
switch (DF) {
case 1:
freq1;
break;
case 2:
freq2;
break;
case 3:
freq3;
break;
case 4:
freq4;
break;
case 5:
freq5;
break;
case 6:
freq6;
break;
default:
break;
}
}
printf("%s%s\n", "Dice's Face", "Face Frequency");
printf("1%lu\n", freq1);
printf("2%lu\n", freq2);
printf("3%lu\n", freq3);
printf("4%lu\n", freq4);
printf("5%lu\n", freq5);
printf("6%lu\n", freq6);
return 0;
}
Example output:
Dice's Face Face Frequency
1 177
2 160
3 166
4 169
5 155
6 173
For reference, a version using an array of 6 ints:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
unsigned long int freqs[6] = {0};
srand(time(NULL));
for (int loop = 0; loop < 1000; loop ) {
freqs[rand() % 6] ;
}
printf("%s%s\n", "Dice's Face", "Face Frequency");
for(int face = 0; face < 6; face ) {
printf("%d%lu\n", face 1, freqs[face]);
}
return 0;
}
CodePudding user response:
Here is an annotated adaptation of your code for educational purposes. You've learned about "loops", so here is an application for a do/while()
loop.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// Global variables are frowned upon because as the code grows more complex
// it is difficult or impossible to see where a value may be changed (inappropriately)
// For a tiny program like this that is unlikely to grow
// this proves the global variables are, by default, initialised to zero.
unsigned long int freq1, freq2, freq3, freq4, freq5, freq6;
int main() {
unsigned long int L00p = 0; // "local" var initialised. Good!
srand( time( NULL ) ); // called once at start of program.
do {
switch( ( rand() % 6 ) ) { // braces consistent with your main()
case 1: freq1; break; // get used to base-0 counting
case 2: freq2; break;
case 3: freq3; break;
case 4: freq4; break;
case 5: freq5; break;
case 0: freq6; break; // Ha-ha!! modulo!!!
default: printf( "A miracle has happened!!\n" );
break;
} // DO NOT hide that closing brace as you did. Prominent!
} while( L00p < 6e3 ); // increment counter after each loop done
// Swapped your output columns
// Using one format specifier for header and one for counts
// Notice how easy to modify only one instance?
char *tFmt = "%9s : %s Loops = %d\n";
char *oFmt = "%9lu : %d\n";
printf( tFmt, "Frequency", "Face", L00p );
// and... why not???
for( L00p = 0; L00p < 6; L00p ) {
int n; // not init'd because used immediately
switch( L00p ) {
case 1: n = freq1; break;
case 2: n = freq2; break;
case 3: n = freq3; break;
case 4: n = freq4; break;
case 5: n = freq5; break;
case 0: n = freq6; break;
}
printf( oFmt, n, L00p 1 );
}
return 0;
}
Output
Frequency : Face Loops = 6000
958 : 1
1038 : 2
1018 : 3
1031 : 4
956 : 5
999 : 6
Again, for a simple, small piece of code like this, being able to see the entire switch
block and compare values at a glance, concatenating statements can AID in writing bug-free code.