首页 > 解决方案 > (为什么)std::binomial_distribution 对大概率 p 有偏差,而对小 n 则慢?

问题描述

我想在 C++ 中生成二项式分布的随机数。速度是一个主要问题。不太了解随机数生成器,我使用标准库的工具。我的代码如下所示:

#include <random>

static std::random_device random_dev;
static std::mt19937 random_generator{random_dev()};
std::binomial_distribution<int> binomial_generator;

void RandomInit(int s) {
    //I create the generator object here to save time. Does this make sense?
    binomial_generator = std::binomial_distribution<int>(1, 0.5);
    random_generator.seed(s);
}

int binomrand(int n, double p) {
    binomial_generator.param(std::binomial_distribution<int>::param_type(n, p));
    return binomial_generator(random_generator);
}

为了测试我的实现,我构建了一个 cython 包装器,然后从 python 中执行并计时该函数。作为参考,我还实现了一个“愚蠢的”二项分布,它只返回伯努利试验的总和。

int binomrand2(int n, double p) {
    int result = 0;
    for (int i = 0; i<n; i++) {
        if (_Random() < p) //_Random is a thoroughly tested custom random number generator on U[0,1)
            result++;
    }

    return result;
}

时序表明,后者的实现比前者快 50% 左右n < 25。此外,对于p = 0.95,前者产生了显着偏差的结果(超过 1000000 次试验的平均值为n = 4038.23037标准差为0.0014;结果可通过不同的种子重现)。

这是标准库功能的(已知)问题还是我的实现错误?我可以做些什么来实现高效获得准确结果的目标?

该参数n将大多低于100,较小的值将更频繁地出现。

我对标准库范围之外的建议持开放态度,但我可能无法使用外部软件库。

我在 64 位 Windows 上使用 VC 2019 编译器。

编辑

我还测试了不使用 python 的偏差:

double binomrandTest(int n, double p, long long N) {
    long long result = 0;
    for (long long i = 0; i<N; i++) {
        result += binomrand(n, p);
    }
    return ((double) result) / ((double) N);
}

结果仍然存在偏差(38.228045对于上面的参数,38.000507可能会出现类似的情况)。

标签: c++randomdistribution

解决方案


推荐阅读