写作该文的目的是出于对帖子: 一个骰子有6面, 概率均匀, 我如何选择7件事? 有些疑问和想法
帖子中对8楼的方案呼声最高:
8楼的方案如下:
用一个骰子扔一次得到x, 再仍一次得到y, 如果x, y都为6就不算, 重来
该方案原理是利用表达式(6x-6+y)可以得到[1, 36], 再去除x, y都为6的情形, 得到[1, 35], 这35个数字对7取余后再加1, 就会得到5个1, 5个2, ..., 5个6, 5个7, 故认为((6x-6+y)%7)+1取得[1, 7]中各数的概率是相同的
我当时是这么想的:
U = { 1, 2, 3, 4, 5, 6, 7 }, y = { 1, 2, 3, 4, 5, 6 }, 当x = 6时, y != 6
x = 1, ((6x-6+y)%7)+1 = U - { 1 }, 第一个孩子分不到苹果
x = 2, ((6x-6+y)%7)+1 = U - { 7 }, 第七个孩子分不到苹果
x = 3, ((6x-6+y)%7)+1 = U - { 6 }, 第六个孩子分不到苹果
x = 4, ((6x-6+y)%7)+1 = U - { 5 }, 第五个孩子分不到苹果
x = 5, ((6x-6+y)%7)+1 = U - { 4 }, 第四个孩子分不到苹果
x = 6, ((6x-6+y)%7)+1 = U - { 2, 3 }, 第二个和第三个孩子分不到苹果
为什么x = 6时会使两孩子分不到苹果呢, 另外x, y调换下顺序得到的结果也是不一样的, 也就是说不能用两个骰子一起扔, 这似乎又与时间(顺序有关了), 想到这里我有些疑惑了
虽然有疑惑, 但我又表达不出来, 或者说根本讲不清楚我在疑惑什么, 只是觉得有点不对劲, 所以, 我只好用代码来证实下我的想法:
#include <ctime>
#include <cstdlib>
#include <iostream>
using namespace std;
int counter1[6] = { 0 };
int counter2[6] = { 0 };
int counter3[7] = { 0 };
void show()
{
cout << "******* counter1 *******" << endl;
double total = 0.0;
for (int i = 0; i < 6; ++i) {
total += counter1[i];
}
for (int i = 0; i < 6; ++i) {
cout << " " << (i + 1) << ": " << (counter1[i] / total) << endl;
}
cout << "******* counter2 *******" << endl;
total = 0.0;
for (int i = 0; i < 6; ++i) {
total += counter2[i];
}
for (int i = 0; i < 6; ++i) {
cout << " " << (i + 1) << ": " << (counter2[i] / total) << endl;
}
cout << "******* counter3 *******" << endl;
total = 0.0;
for (int i = 0; i < 7; ++i) {
total += counter3[i];
}
for (int i = 0; i < 7; ++i) {
cout << " " << (i + 1) << ": " << (counter3[i] / total) << endl;
}
}
int random()
{
static int max = RAND_MAX / 6 * 6;
int i = 0;
while (0 == i || i > max) {
i = rand();
}
return (i % 6 + 1);
}
void test(int times)
{
for (int i = 0; i < times; ++i) {
for (int j = 0; j < 7; ++j) {
int r1 = random();
int r2 = random();
++counter1[r1 % 6];
++counter1[r2 % 6];
if (!(6 == r1 && 6 == r2)) {
++counter2[r1 % 6];
++counter2[r2 % 6];
++counter3[(6 * r1 - 6 + r2) % 7];
}
}
}
show();
}
int main()
{
srand(time(NULL));
test(100000000);
return 0;
}
其中random()可以均匀的取得[1, 6], 利用8楼方案扔100000000*7次后, 得到结果如下:
******* counter1 *******
1: 0.16667
2: 0.166665
3: 0.166668
4: 0.166664
5: 0.166663
6: 0.16667
******* counter2 *******
1: 0.142858
2: 0.171428
3: 0.17143
4: 0.171427
5: 0.171425
6: 0.171433
******* counter3 *******
1: 0.14284
2: 0.142871
3: 0.142837
4: 0.142883
5: 0.142866
6: 0.14285
7: 0.142853
其中counter1表明扔骰子得到[1, 6](其实是[6, 1, 2, 3, 4, 5])的概率(其实是频率), 从结果可以看出前四位小数都是相同的, 可知random()的做法是正确的
其中counter2记录的是去掉x=6, y=6这种情况后, 得到[1, 6](其实是[6, 1, 2, 3, 4, 5])的概率(频率), 可以看出得到1少很多, 其实1是骰子的第6面, 得到这样的结果是因为x=6, y=6被去除而少统计了第6面的频数
其中counter3记录的是表达式取[1, 7](其实是[7, 1, 2, 3, 4, 5, 6])的概率(频率), 得到的结果的前四位小数也都是相同的, 说明8楼的方案从结果上看是对的
再回到我的疑惑, 我的疑惑无非是感觉[2, 3]号小孩似乎吃亏了, "凭什么, 第一次扔得6时, 我们俩(2, 3)注定没戏了, 而第一次扔得不是6, 只有一个家伙注定没戏?", 确定第一次扔得不是6时, 会有一个家伙注定没戏, 但第一次扔得6后, 初看(2, 3)两个似乎是没戏了, 但其实他们还有一次重生的机会, 此时第二次也扔得6
其实上面(本人的)各想法只是主观臆断, 就像空袭时, 士兵会跳入前一炸出的炕一样, 毫无科学根据, 但我们喜欢跟着感觉走
冷静下来, 分析下8楼的方案, 其实很快可以得到证明:
第1个小孩得到苹果的情况为:
(x, y) = { (2, 1), (3, 2), (4, 3), (5, 4) } + { (6, 5) } + { Part(6, 6) };
p(1) = 4 * (1/6) * (1/6) + (1/6) * (1/6) + (这一次不算, 重来后的某一次得到)
第{4, 5, 6, 7}个小孩与第1个小孩同样可得到这个概率
下面分析第2个小孩得到苹果的情况:
(x, y) = { (1, 1), (2, 2), (3, 3), (4, 4), (5, 5) } + { Part(6, 6) };
p(2) = 5 * (1/6) * (1/6) + (这一次不算, 重来后的某一次得到)
第3个小孩与第2个小孩将得到相同的概率
综上, 只要在(x, y) = (6, 6)时, 七个小孩得到苹果的概率相同时, 那么p(i)对于1-7的值就是相同的
令p1 = (5 / 36), 利用p1代入表达式(p1 + (1 - 7 * p1) * p1), 将表达式结果赋给p1再代入表达式计算...最后的结果就是p(i)的值为(1/7), 这是个求级限的问题(怎么求忘了)
综上, 8楼的答案是对的