Почему GCC и MSVC std:: normal_distribution отличаются?

У меня есть простой пример кода:

#include <iostream>
#include <random>
using namespace std;
int main() {
    minstd_rand0 gen(1);
    uniform_real_distribution<double> dist(0.0, 1.0);
    for(int i = 0; i < 10; ++i) {
        cout << "1 " << dist(gen) << endl;
    }

    normal_distribution<double> dist2(0.0, 1.0);
    minstd_rand0 gen2(1);
    for(int i = 0; i < 10; ++i) {
        cout << "2 " << dist2(gen2) << endl;
    }

    return 0;
}

Что я компилирую на gcc и msvc, Я получаю разные результаты по std-коду! ( введите описание изображения здесь

Итак, почему результаты GCC и MSVC std::normal_distribution отличаются друг от друга для одного и того же семени и генератора и, самое главное, как заставить их быть одинаковыми?

Ответ 1

Это проблематично, но, к сожалению, в стандарте подробно не указывается, какой алгоритм использовать при построении (многих) случайным образом распределенных чисел, и существует несколько допустимых альтернатив с различными преимуществами.

26.6.8.5 Normal distributions [rand.dist.norm] 26.6.8.5.1 Class template normal_distribution [rand.dist.norm.normal]

Распределение случайных чисел при нормальном распределении производит случайное числа x распределены в соответствии с функцией плотности вероятности

enter image description here

параметры μ и также известны как это среднее распределение и стандартное отклонение.

Наиболее распространенным алгоритмом генерации нормально распределенных чисел является Box-Muller, но даже с этим алгоритмом есть варианты и варианты.

Свобода даже явно упоминается в стандарте:

26.6.8 Random number distribution class templates [rand.dist] ...

3 Алгоритмы для получения каждого из указанных распределений реализации.

Варианты перехода для этого: повысить случайность

Кстати, как указывает @Hurkyl: кажется, что две реализации на самом деле одинаковы: например, box-muller генерирует пары значений, одно из которых возвращается, а другое кэшируется. Две реализации отличаются только тем, какое из значений возвращается.

Кроме того, механизмы случайных чисел полностью определены и будут давать одинаковую последовательность между реализациями, но необходимо соблюдать осторожность, поскольку различные распределения могут также потреблять разные объемы случайных данных для получения своих результатов, что приведет к потере этих механизмов. синхронизации

Ответ 2

В отличие от генераторов PRN, определенных стандартом, который должен выдавать один и тот же результат для одного и того же семени, стандарт не сохраняет этот мандат для дистрибутивов. Из [rand.dist.general]/3

Алгоритмы для создания каждого из указанных распределений определяются реализацией.

Итак, в этом случае, хотя распределение должно иметь функцию плотности в виде

введите описание изображения здесь

Как осуществляется реализация с ними.

Единственный способ получить переносимый дистрибутив - написать его самостоятельно или использовать стороннюю библиотеку.