OS X libc++ std::uniform_real_distribution bug
OS X libc++ std::uniform_real_distribution bug
在使用Apple LLVM 7.0.2版(clang-700.1.81)编译C++11的std::uniform_real_distribution
时,我看到了一些奇怪的行为。调用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
会调用该术语四次出现中的第一次。
顺便说一句,你的代码中也有一个bug。那些神奇的数字273673163155和13应该是以8为底。这些是drand48
使用的数字。随机选取a
、c
和m
的值几乎肯定会导致坏的随机数生成器。
我建议切换到std::mt19937
或std::mt19937_64
。
相关文章:
- 点运算符 (.) 是"real"运算符吗?
- 常量参数"real"常量吗?
- C ++引用函数参数似乎包含原始对象的副本,而不是充当"real reference"
- 在调试中,如何知道对函数的重复调用中参数的统计数据(max-min,average,distribution..)
- Box muller distribution
- QML/real和C++/float之间的Qt类型错误
- 在日食中获取无法执行 g++.real 错误
- 了解"Real world modelling"程序
- 使用 BER 编码和解码 ASN.1 REAL
- LLVM Callinst 函数如何获取 (real)Name
- boost::math::p df(distribution, value) 是否使用查找表或在每次调用时计算 exp(
- <double> 复杂C++ - 不能使用 imag()、complex()、real()
- 实现QProcess的最佳方法是什么,在"real time"中读取stdout和stderr?
- Dirichlet distribution with RcppGSL
- 如何查找"real"错误?
- 关于渲染系统架构布局的建议-Real time/HLSL/DirectX9/ c++
- MPI distribution layer
- SQLite文本转换为整数或REAL在c++做太多