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.01.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!)


  • 【C++11】有趣的数学与随机数生成库

  • 考虑n = 3
    等价于,在棱长为 1 的正方体中取一点,其落在箭头区域(x + y + z > 1)的概率,即P = 5/6 = 1 - 1 / (3!)


  • 【C++11】有趣的数学与随机数生成库

  • ….

为了不让证明过程过于复杂,我们直接给出一个数学定理:n维单位空间中,其中任取一点,落在单位之外的概率为 P = 1 - 1 / (n!)

在我们的问题中,考虑“第n次选择后,其和恰好大于 1 ”的事件。该事件成立的前提是,前 n-1 的和并未大于 1 ,而第 n 次选择之后,其和大于 1 。则有:

【C++11】有趣的数学与随机数生成库

上式中后半部分减去的是“前n-1次选择后和大于 1 ”的概率。如此一来,我们的问题便能够求解了。

【C++11】有趣的数学与随机数生成库

由泰勒级数我们知道,【C++11】有趣的数学与随机数生成库 = e。
证毕。

【C++11】有趣的数学与随机数生成库

点分享

点点赞

点在看

以上是关于C++11有趣的数学与随机数生成库的主要内容,如果未能解决你的问题,请参考以下文章

AI探索NumPy库的使用

NumPy

Python标准库12 数学与随机数 (math包,random包)

使用 C++11 随机库生成随机数

C++11中的随机数生成:如何生成,它是如何工作的? [关闭]

科学计算和可视化