C++11有趣的数学与随机数生成库
Posted 编程笔记本
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++11有趣的数学与随机数生成库相关的知识,希望对你有一定的参考价值。
今天我们来看一个有趣的问题:
不断从[0,1]
中随机选择一个数进行累加,直到其和超过1
,需要选择几次?
对于一次特定的实验,次数是一个确定的整数。我们要讨论的是,选择次数的数学期望。或者说,平均需要多少次。
现在,这已经变成了一个比较复杂的数学问题了。但是,好在问题描述并不复杂,我们可以用计算机进行数值模拟。
程序流程图:
step1: 设
s=0
;
step2: 从[0,1]
中随机选择一个数x
;
step3:s=s+x
;
step4: 若s>1
,停止;否则转到step2。
参考c++代码:
#include <stdio.h>
#include <random>
#include<iomanip>
int main()
{
// 设置随机数生成器
std::default_random_engine e(time(0));
std::uniform_real_distribution<double> gen(0.0, 1.0);
double sum = 0.0;
int cnt = 0;
// 总试验次数与总选择次数
int times = 100;
long long all = 0;
for (int i = 0; i < times; ++i) {
sum = 0;
cnt = 0;
while (sum <= 1.0) {
sum += gen(e);
++cnt;
}
all += cnt;
}
// 选择次数期望 = 总选择次数 / 总试验次数
double exp = double(all) / double(times);
printf("exp = %.5lf\n", exp);
}
下面我们运行程序:
jincheng@DESKTOP-42T69DJ:/mnt/e/LinuxSubSysFile$ g++ test.cpp
jincheng@DESKTOP-42T69DJ:/mnt/e/LinuxSubSysFile$ ./a.out
exp = 2.74012
从实验结果可以看到,当我们进行100次这样的实验,得到的平均选择次数为2.74012
。
当然了,既然是验证性实验,100
次还是太少了,下面我们修改times
变量值,增加试验次数,再来观察实验结果。
times = 1000
exp = 2.72800
times = 10000
exp = 2.71440
times = 100000
exp = 2.71601
times = 1000000
exp = 2.71939
times = 10000000
exp = 2.71833
times = 100000000
exp = 2.71824
随着实验的进行,我们似乎看出来某种规律,选择次数的期望值怎么这么眼熟啊……是不是有点像自然对数底数e
啊?
我们知道,自然对数底数e = 2.71828 18284 59……
。当我们进行足够多次实验(100000000次)时,得到的选择次数期望值为2.71824
,这与e
的前四位小数惊人般地雷同!直觉告诉我,这一定不是巧合!此事必有蹊跷!
先说结论:
不断从
[0,1]
中随机选择一个数进行累加,直到其和超过1
,需要的选择次数的期望值为欧拉常数e
。
今天的编程小知识主要是C++11新标准的随机数生成库的应用。在新标准下使用随机数,原则上我们不再使用rand()
与srand()
函数了,而是使用随机度更高、效率更快的随机数生成库,它内置了一系列常用的随机分布。感兴趣的小伙伴可以自行查阅学习。下面是上述结论的严格数学证明,请小伙伴们有选择性地阅读。
求数学期望,就是随机量的所有可能取值*
随机量取该值的概率。
在我们讨论的问题中,选择次数(记为C
)的可能取值为:2,3,4,...
,则:
下面我们从简单的情况入手。
考虑
n = 2
:
等价于,在边长为 1 的正方形中取一点,其落在箭头区域(x + y > 1
)的概率,即P = 1/2 = 1 - 1 / (2!)
;考虑
n = 3
:
等价于,在棱长为 1 的正方体中取一点,其落在箭头区域(x + y + z > 1
)的概率,即P = 5/6 = 1 - 1 / (3!)
;….
为了不让证明过程过于复杂,我们直接给出一个数学定理:在n
维单位空间中,其中任取一点,落在单位之外的概率为 P = 1 - 1 / (n!)
。
在我们的问题中,考虑“第n
次选择后,其和恰好大于 1 ”的事件。该事件成立的前提是,前 n-1
的和并未大于 1 ,而第 n
次选择之后,其和大于 1 。则有:
上式中后半部分减去的是“前n-1
次选择后和大于 1 ”的概率。如此一来,我们的问题便能够求解了。
由泰勒级数我们知道, = e。
证毕。
点分享
点点赞
点在看
以上是关于C++11有趣的数学与随机数生成库的主要内容,如果未能解决你的问题,请参考以下文章
Python标准库12 数学与随机数 (math包,random包)