写作该文的目的是出于对帖子: 一个骰子有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楼的答案是对的

本文针对使用一个六面骰子实现七等分概率的选择问题进行了深入探讨,并通过编程实验验证了提出的解决方案的有效性。
1万+

被折叠的 条评论
为什么被折叠?



