std :: normal_distribution результат для того же значения генератора? - PullRequest
0 голосов
/ 08 ноября 2018

Я заметил очень странное поведение со стандартной библиотекой 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

Посмотрите, как результаты dist1 в строках 0 и 5 отличаются, даже если генератор выдает одно и то же значение 1. Для dist2 они такие же, как мы называем reset().

Кстати, причина в том, что библиотека GNU C ++ генерирует значения в парах и кэширует их между вызовами, необязательно вызывая генератор. Это также объясняет, почему строка 4 dist1 совпадает со строкой 2. dist2 (которая сбрасывает распределение).

Я искал в документации, но не мог понять, соответствует ли это поведение стандарту. Следовательно, я не знаю, является ли это стандартной ошибкой библиотеки:)

Обратите внимание, из того, что я видел, std :: normal_distribution - единственный класс, демонстрирующий такое поведение.

1 Ответ

0 голосов
/ 08 ноября 2018

Это соответствует стандарту. Не требуется, чтобы генератор не имел состояния. Если бы это было так, функция reset не имела бы смысла.

...