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