Home > Net >  Strange behaviour in a Dice Throwing simulation program
Strange behaviour in a Dice Throwing simulation program

Time:09-13

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:

Programme's output

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. Calling srand() with the same number (and time(NULL) will quite inevitably return the same second in a tight loop) will reset the rand() generator to return the same sequence of numbers, and since you only ever call rand() once before calling srand() 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.

  • Related