[英]OS X libc++ std::uniform_real_distribution bug
我在使用C ++ 11的std::uniform_real_distribution
编译Apple LLVM版本7.0.2(clang-700.1.81)时看到了一些奇怪的行为。 调用operator()会在分布范围之外呈现结果。 下面的最小样本程序再现了麻烦
// Example program
#include <random>
#include <iostream>
#include <string>
template< int power >
constexpr uint64_t power_of_two(){
return 2 * power_of_two< power - 1 >();
}
template< >
constexpr uint64_t power_of_two< 0 >(){
return 1;
}
std::linear_congruential_engine
< uint64_t, 273673163155, 13, power_of_two< 48 >() >
rng;
std::uniform_real_distribution< double > angle_cosine(-1, 1);
int main()
{
std::cout << angle_cosine.a() << " " << angle_cosine.b() << '\n' << std::endl;
for (int i = 0; i < 4; ++i){
std::cout << angle_cosine(rng) << std::endl;
}
}
在线编译和运行(大概用g ++)可以得到合理的结果
-1 1
-0.529254
-0.599452
0.513316
-0.604338
但是,在本地编译和运行会产生不合理的结果。
-1 1
130349
37439.4
42270.5
45335.4
我是否忽略了某些内容或者我遇到过libc ++中的错误? 如果是后者,是否有人知道解决方案?
这是LLVM线性同余生成器中的一个错误,而不是统一的实际分布中的错误。 均匀实分布假定生成器返回的数字介于生成器的最小值和最大值(包括)之间。 这是任何发电机的要求。 具有这组数字的LLVM线性同余生成器无法满足该要求。
LLVM线性同余生成器使用旧算法来避免溢出称为Schrage算法,而不是(a*x+c)%m
用于您的数字集。 该算法的LLVM实现几乎可以保证您的a, c, m
集合将生成大于m
数字。
您可以在此处查看LLVM代码: https : //llvm.org/svn/llvm-project/libcxx/trunk/include/random 。 搜索'Schrage算法'。 您选择a
, c
和m
调用该术语的四次出现中的第一次。
顺便说一句,你的代码中也存在一个错误。 那些神奇的数字273673163155和13应该是基数8.这些是drand48
使用的数字。 随机选择a
, c
和m
值几乎肯定会导致错误的随机数生成器。
我建议切换到std::mt19937
或std::mt19937_64
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.