【问题标题】:OS X libc++ std::uniform_real_distribution bugOS X libc++ std::uniform_real_distribution 错误
【发布时间】:2016-05-23 03:17:04
【问题描述】:

我看到使用 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;
    }
}

编译运行online(大概用g++)会呈现合理的结果

-1 1

-0.529254
-0.599452
0.513316
-0.604338

但是,在本地编译运行会呈现不合理的结果。

-1 1

130349
37439.4
42270.5
45335.4

我是否忽略了某些事情或遇到了 libc++ 中的错误?如果是后者,是否有人知道解决方法?

【问题讨论】:

  • 对我来说似乎是一个错误。它与a、c 和m 的值的选择有关。它适用于here 列出的大多数流行选择,但对于 m=2^48 的这两个设置则失败了

标签: c++ c++11 random libc++


【解决方案1】:

这是 LLVM 线性同余生成器中的错误,而不是均匀实数分布中的错误。均匀实数分布假设生成器返回的数字介于生成器的最小值和最大值(含)之间。这是任何发电机的要求。具有这组数字的 LLVM 线性同余生成器无法满足该要求。

LLVM 线性同余生成器使用一种旧算法来避免溢出,称为 Schrage 算法,而不是用于您的一组数字的 (a*x+c)%m。该算法的 LLVM 实现实际上保证了您的 a, c, m 集合将生成大于 m 的数字。

您可以在此处查看 LLVM 代码:https://llvm.org/svn/llvm-project/libcxx/trunk/include/random。搜索“施拉格算法”。您选择的a、c 和m 会调用该术语的四个出现中的第一个。

顺便说一句,您的代码中也有一个错误。那些神奇的数字 273673163155 和 13 应该是基数 8。这些是 drand48 使用的数字。随机选取 a、c 和 m 的值几乎肯定会导致错误的随机数生成器。

我建议切换到std::mt19937 或std::mt19937_64。

【讨论】:

  • 令人印象深刻的答案!
  • 我在 LLVM bugzilla 数据库的 std::linear_congruential_generator(甚至“congruential”)上找不到任何东西,所以我提交了一份错误报告。
  • 首先,感谢您的全面回答。其次,感谢您提交错误报告。您认识到我在实现 drand48 方面的失败尝试给我留下了深刻的印象,甚至发现我的疏忽将 drand48 常量从八进制转换为十进制。
  • 感谢您的错误报告。
  • @apmccartney - 不客气! (还有你,马歇尔)。错误报告是llvm.org/bugs/show_bug.cgi?id=27839。
猜你喜欢
  • 2012-11-09
  • 1970-01-01
  • 2013-04-05
  • 1970-01-01
  • 1970-01-01
  • 2013-04-19
  • 2014-03-15
  • 1970-01-01
  • 2017-03-06
相关资源
最近更新 更多