Big Fish

2009-06-05

概率问题

有个经典概率问题是这样的:三个门,其中一个后面是轿车,另外两个后面是山羊,你任选一个门,如果打开了后面是汽车,汽车就归你。你选了一个门后,主持人打开了另一个门,后面是山羊。这时他给你一个机会更改自己的选择,你要坚持自己一开始的选择还是更改自己的选择?这个问题很有名,比如电影21里面也提到过(btw, 这个电影很一般,没看过的就不用浪费时间了)。

答案是更改选择。因为不改的话你选对的概率是1/3,而改了你选对的概率变成2/3。

昨天杨爷不知道为啥又把这个问题翻出来了,然后跟我们讨论为啥不是1/2。我概率学的不够好,没找到足够让人信服的理由反驳他的1/2。不过我C语言学的比较好,而且正好今天休假比较闲,于是中午写了个程序模拟了一下。。。这个是跑很多次的结果:

fishy@Makelele:~/work/test$ ./test 100000
CHANGE
*** right on 66706 out of 100000, 66.71% ***
NO CHANGE
*** right on 33331 out of 100000, 33.33% ***
fishy@Makelele:~/work/test$ ./test 1000000
CHANGE
*** right on 667107 out of 1000000, 66.71% ***
NO CHANGE
*** right on 332750 out of 1000000, 33.28% ***
fishy@Makelele:~/work/test$ ./test 10000000
CHANGE
*** right on 6666707 out of 10000000, 66.67% ***
NO CHANGE
*** right on 3334351 out of 10000000, 33.34% ***

这个是只跑了20次但是给出具体内容的结果:

fishy@Makelele:~/work/test$ ./test 20 a
CHANGE
guess 1, show 0, changed to 2, result is 2
guess 0, show 1, changed to 2, result is 2
guess 1, show 2, changed to 0, result is 0
guess 0, show 1, changed to 2, result is 2
guess 0, show 2, changed to 1, result is 0
guess 1, show 2, changed to 0, result is 0
guess 2, show 0, changed to 1, result is 1
guess 0, show 1, changed to 2, result is 0
guess 2, show 0, changed to 1, result is 2
guess 0, show 2, changed to 1, result is 1
guess 0, show 2, changed to 1, result is 1
guess 0, show 2, changed to 1, result is 0
guess 0, show 2, changed to 1, result is 0
guess 1, show 0, changed to 2, result is 2
guess 0, show 2, changed to 1, result is 1
guess 0, show 1, changed to 2, result is 2
guess 2, show 1, changed to 0, result is 0
guess 2, show 1, changed to 0, result is 0
guess 1, show 0, changed to 2, result is 2
guess 0, show 2, changed to 1, result is 1
*** right on 15 out of 20, 75.00% ***
NO CHANGE
guess 2, show 1, changed to 2, result is 0
guess 1, show 2, changed to 1, result is 0
guess 1, show 0, changed to 1, result is 1
guess 1, show 2, changed to 1, result is 0
guess 0, show 2, changed to 0, result is 1
guess 2, show 0, changed to 2, result is 1
guess 1, show 0, changed to 1, result is 1
guess 0, show 2, changed to 0, result is 0
guess 1, show 2, changed to 1, result is 1
guess 0, show 1, changed to 0, result is 2
guess 1, show 2, changed to 1, result is 0
guess 0, show 1, changed to 0, result is 0
guess 1, show 2, changed to 1, result is 0
guess 0, show 1, changed to 0, result is 2
guess 0, show 1, changed to 0, result is 2
guess 1, show 0, changed to 1, result is 2
guess 0, show 1, changed to 0, result is 0
guess 1, show 0, changed to 1, result is 1
guess 0, show 2, changed to 0, result is 1
guess 0, show 2, changed to 0, result is 1
*** right on 7 out of 20, 35.00% ***

所以很显然了,换了猜对的概率是2/3,不换是1/3。

下面是程序

 1 #include <stdio.h>
 2 #include <time.h>
 3 #include <stdlib.h>
 4
 5 typedef int changefunc(int, int);
 6
 7 int change(int guess, int show) {
 8         return 0+1+2 - guess - show;
 9 }
10
11 int nochange(int guess, int show) {
12         return guess;
13 }
14
15 void loop(int times, changefunc func, int print) {
16         int i, n;
17         n = 0;
18         for(i=0;i<times;i++) {
19                 int target = rand() % 3;
20                 int guess = rand() % 3;
21                 int show, finalguess;
22                 if(guess != target)
23                         show = 0+1+2 - target - guess;
24                 else {
25                         show = guess + rand() % 2 + 1;
26                         if(show >= 3) show -= 3;
27                 }
28                 finalguess = func(guess, show);
29                 if(print)
30                         printf("guess %d, show %d, changed to %d, result is %d\n", guess, show, finalguess, target);
31                 if(target == finalguess) n++;
32         }
33         printf(" *** right on %d out of %d, %.2f%% ***\n", n, times, ((double)n)/times*100);
34 }
35
36 int main(int argc, char **argv) {
37         if(argc <= 1)
38                 return -1;
39         int times = atoi(argv[1]);
40         int print = (argc >= 3);
41         srand(time(0));
42         // change
43         printf("CHANGE\n");
44         loop(times, change, print);
45         // no change
46         printf("NO CHANGE\n");
47         loop(times, nochange, print);
48         return 0;
49 }

要是能天天都休假还有工资拿就好了。。。

00:05:00 by fishy - Permanent Link

May the Force be with you. RAmen