设random()是给定的随机数发生器。
1.开始想直接 random() * 10 / 7,不行:这就是个一一映射,结果仍只有7种。
2.原均值为4,设想(random() + random() + random() + random() + random() ) / 4,那会儿已经开始胡思乱想,巫毒编程了
这种方法结果更差,事实上这种变换得到的甚至不是均匀分布,有点象正态分布了。
3.先扩大,再试图通过除法或模运算来限定到1~10,不知基于什么理论,朴素地感觉不靠谱。
4.打开本《概率论》,翻到《离散随机变量的函数》,哦,变换后要对值相等的结果进行概率合并。
乘以常数是不能扩展值域的,取两个随机变量相乘可以。统计下:
#include <iostream>
#include <iostream>
#include <iomanip>
using namespace std;int prod_cnt[50];
int cnt_cnt[50];int main()
{
for(int i = 1; i <= 7; ++i){
for(int j = 1; j <= 7; ++j){
prod_cnt[i*j] += 1;
}
} int max_cnt = 0;
for(int i = 0; i < 50; ++i){
if(prod_cnt[i] > max_cnt){ // 记住出现最多的次数
max_cnt = prod_cnt[i];
}
if(prod_cnt[i] >= 1){
cout << setw(3) << i << setw(3) << prod_cnt[i] << endl;
}
} for(int i = 0; i < 50; ++i){
++cnt_cnt[prod_cnt[i]];
}
for(int i = 1; i <= max_cnt; ++i){
cout << "cnt " << i << " occurs " << setw(3) << cnt_cnt[i] << endl;
}
}
结果:(第一列是积,第二列是出现的次数,如6出现四次:1*6 6*1 2*3 3*2)
1 1
2 2
3 2
4 3
5 2
6 4
7 2
8 2
9 1
10 2
12 4
14 2
15 2
16 1
18 2
20 2
21 2
24 2
25 1
28 2
30 2
35 2
36 1
42 2
49 1
cnt 1 occurs 6
cnt 2 occurs 16
cnt 3 occurs 1
cnt 4 occurs 2
需要找到至少10种概率相等(出现次数相等)的积:
出现次数为1、3、4的结果总数都不够,只有次数为2的可用,从中任选10种,替换为1到10即可。测试:
#include <iostream>
#include <iomanip>
using namespace std;
#include "wzRandom64.hpp"
class Rand10
{
wz::Random64 m_rng;
public:
long long gen()
{
long long x = 0;
do{
x = m_rng.genIntBetween(1, 7) * m_rng.genIntBetween(1, 7);
switch(x){
case 2: x = 1; break;
case 3: x = 2; break;
case 5: x = 3; break;
case 7: x = 4; break;
case 8: x = 5; break;
case 10: x = 6; break;
case 14: x = 7; break;
case 15: x = 8; break;
case 18: x = 9; break;
case 20: x = 10; break;
default:
x = 0; break;
}
}while(x == 0);
return x;
}
};
int const AVG_CNT = 1000000;
int const RESULT_CNT = 10;
int const TOTAL_CNT = AVG_CNT * RESULT_CNT;
int counter[RESULT_CNT + 1];
int main(int argc, char const * argv[])
{
Rand10 rng;
for(int i = 0, x; i < TOTAL_CNT; ++i){
x = rng.gen();
++counter[x];
}
for(int i = 1; i <= RESULT_CNT; ++i){
cout << "[" << setw(2) << i << "] " << setw(10) << counter[i] << setw(12) << setprecision(8) << fixed << (counter[i] - AVG_CNT)*1.0 / AVG_CNT << '\n';
}
}
其中wz::Random64是个根据Mersenne Twister 64位版 改写的伪随机数发生器。