【问题标题】:std::normal_distribution result for the same generator value?相同生成器值的 std::normal_distribution 结果?
【发布时间】:2018-11-08 01:09:53
【问题描述】:

我注意到 GNU C++ 标准库的一个非常奇怪的行为。

当使用具有正态分布的自定义生成器时,即使对于相同的生成器结果,分布似乎也可能返回不同的值。

示例代码

#include <iostream>
#include <string>
#include <random>

template <int MAX>
class Generator
{
public:
  long long operator()() {return (++state) % MAX;}
  long long min() {return 0;}
  long long max() {return MAX;}
  long long state = 0;
};

int main()
{
  // 3 identical generators, 2 identical distributions
  Generator<5> gen0, gen1, gen2;
  std::normal_distribution<float> dist1(10, 1), dist2(10,1);

  // Print: iteration, generator output, distributions output
  printf("i   gen       dist1      dist2\n");    
  for (int i = 0; i < 10; i++) {
    printf("%d     %lld  %10.6f %10.6f\n", i, gen0(), dist1(gen1), dist2(gen2));
    dist2.reset();
  }

}  

这会产生(g++ 6.2.1,在较新的版本上相同):

i   gen       dist1      dist2
0     1   11.295982  11.295982
1     2    9.325577  10.256990
2     3   10.256990   9.672720
3     4    8.679697   9.300377
4     0    9.672720   8.957100
5     1    9.097454  11.295982
6     2    9.300377  10.256990
7     3   10.582899   9.672720
8     4    8.957100   9.300377
9     0   10.169774   8.957100

查看第 0 行和第 5 行中的 dist1 结果如何不同,即使生成器生成相同的值 1。对于dist2,它们是相同的,我们称之为reset()

顺便说一句,原因似乎是 GNU C++ 库成对生成值,并在调用之间缓存它们,不一定调用生成器。这也解释了为什么 dist1 第 4 行与 dist2(重置分布)第 2 行相同。

我在文档中进行了搜索,但无法确定此行为是否符合标准。因此,我不知道这是否是标准库错误:)

注意,据我所见,std::normal_distribution 是唯一表现出这种行为的类。

【问题讨论】:

    标签: c++ random normal-distribution c++-standard-library


    【解决方案1】:

    它符合标准。不要求生成器是无状态的。如果有,reset 函数将毫无用处。

    【讨论】:

    • 谢谢。确实,似乎所有随机生成器都有这种方法。
    • 顺便说一句,我认为这可能很明显,但是标准中的什么保证初始化或 reset() 之后的行为与 dist2 的行为一致?
    • @MarcinZukowski 我手头没有文字,但标准明确规定生成器的内部状态已重置,因此未来的结果不依赖于过去的操作。
    猜你喜欢
    • 2019-01-12
    • 1970-01-01
    • 2016-02-08
    • 1970-01-01
    • 2019-06-16
    • 2021-02-25
    • 1970-01-01
    • 1970-01-01
    • 2012-07-02
    相关资源
    最近更新 更多