c++ - (为什么)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 = 40
;38.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
可能会出现类似的情况)。
解决方案
推荐阅读
- parameters - 处理类和实例问题
- javascript - jQuery popover 在 Django 应用程序中不起作用?
- reactjs - 在 http-proxy-middleware 的 setupProxy.js 中反应导入环境生成意外标识符
- php - 如何根据当前登录用户codeigniter获取/检索数据,但外键连接到另一个外键
- c# - 在 Unity 中应用多个旋转
- mysql - 参数化查询 - M 语言 (Excel)
- reactjs - 有没有办法为 ReactJs 中的 material-ui 组件提供全局类?
- azure - 从 Azure 数据工厂中的 API 获取而不复制 URL
- c# - 如何用军事时间进行简单的计算?
- angular - 如何根据 HTTP 响应限制/停止 Angular 应用程序加载