/* monty_hall.c by Martin Bazant, 2/13/02 Intro to Modeling and Simulation To compile type: gcc monty_hall.c -o monty_hall -lm or g++ -o monty_hall.c monty_hall To run for 1000 trials of 3 doors with Monty opening 1 type: monty_hall 3 1 1000 (Without any arguments, you just get instructions.) */ /* INCLUDE C LIBRARIES */ #include /* library for input/output */ #include /* library with rand() and srand() */ #include /* library with floor()*/ #include /* library to get the current time */ /* DEFINITIONS */ #define MAX_DOORS 100 /* maximum number of doors n */ /* FUNCTIONS */ int my_rand(int p,int q) /* my_rand(p,q) returns an integer between p and q inclusive. */ { /* NOTE: rand() returns a random integer between 0 and a very large number RAND_MAX. rand()/(RAND_MAX+1) is between 0 and 1 (not inclusive), so this times |p-q|+1 is between 0 and |p-q|+1 (not inclusive). Rounding down to the nearest integer gives us a random integer between 0 and |p-q| (inclusive). We use this method over something similar like rand() % |p-q| + 1, as the latter uses the low order bits of the random number. These are, in general, somewhat less random than the high order bits. It is not usually good to treat _bits_ of a pseudo-random number as random. For many purposes, the difference is academic, but for some applications it makes a difference. See _Numerical Recipes in C_ for some discussion and more references. */ int delta; int shift_from_zero; if(p > q) { delta = p - q; shift_from_zero = q; } else { delta = q - p; shift_from_zero = p; } return shift_from_zero+(int)floor((float)rand() /((float)RAND_MAX+1.0)*(float)(delta+1)); } /* MAIN PROGRAM */ int main(int argc, char *argv[]) { /* VARIABLE DECLARATIONS */ int m,n,trials=100; int wins=0; int num_open,test_door,found_door,i,j; int door[MAX_DOORS]; /* array entries for doors = 0 if unopened and no prize, = 1 if prize, =2 if opened */ float p,p_stay; /* PROCESS COMMAND-LINE INPUT */ if(argc < 3) { printf(" USAGE: monty_hall [] \n"); printf(" n = number of doors available\n"); printf(" m = number of doors opened by Monty\n"); printf(" trials = number of computer experiments\n"); exit(1); } n = atoi(argv[1]); /* convert command-line characters to integers */ if(n < 3 || n > MAX_DOORS) { printf("Error: need 3 < n < MAX_DOORS.\n"); exit(1); } m = atoi(argv[2]); if(m > n-2 || m < 0) { printf("Error: need 0 <= m <= n-2.\n"); exit(1); } if(argc > 3) { trials = atoi(argv[3]); } /* SEED RANDOM NUMBER GENERATOR */ srand(time(NULL)); /* "Seed" the generator with the current time to get a fresh random number. (If not, you always get the same sequence starting from seed=1 when you run the program again, which means you are not getting new data if you run the program more than once.) */ /****** LOOP OVER COMPUTER EXPERIMENTS ******/ for(i=0;i p_stay) { printf("\n Switching doors appears to be helpful,\n"); printf(" since you expect to win only %f \n",100*p_stay); printf(" of the time if you stick with your original choice.\n"); } }