#c #c 11 #random #stl #cross-platform
#c #c 11 #Случайный #stl #кроссплатформенный
Вопрос:
Почему результат стандартных распределений не обязательно должен быть согласованным во всех реализациях? С другой стороны, результат работы генераторов псевдослучайных чисел должен быть идентичным.
Например, следующее почти наверняка напечатает что-то другое для каждой отдельной реализации стандартной библиотеки.
std::mt19937 random {100};
std::normal_distribution<> dist;
std::cout << dist(random);
Допустим, я хочу выполнить процедурную генерацию и хотел бы, чтобы идентичные начальные значения приводили к идентичным результатам на разных платформах и компиляторах. Я не могу сделать это с stl. Я должен «регрессировать» к использованию boost. Почему это не является дефектом?
Комментарии:
1. Это не должно быть ответом, это просто то, о чем стоит подумать . Для многих дистрибутивов существует множество способов получения желаемых значений. Нормальное распределение может использовать преобразование Бокса-Мюллера или функцию ошибок (рекурсивное разложение или Тейлора). Обе эти функции использования используют другие функции (такие как косинус, синус, логарифм, функция ошибки, интегралы, квадратный корень …). Трудно сказать, какой метод является лучшим (время в сравнении с точностью), и который может быть наилучшим образом оптимизирован. Возможно, в C 14, когда люди лучше познакомятся с этими дистрибутивами и реализациями, будет введен стандарт.
2. О, и даже преобразование бокса-Мюллера имеет разные (полярные, декартовы) реализации. Множество способов получить массу удовольствия?
3. @user2899162 у вас действительно есть правильное обоснование, я цитирую предложение в своем ответе.
Ответ №1:
Это не дефект, это задумано. Обоснование этого можно найти в Предложении добавить расширяемый инструмент случайных чисел в стандартную библиотеку (N1398), в котором говорится (курсив мой):
С другой стороны, спецификации для распределений определяют только статистический результат, а не точный алгоритм для использования. Это отличается от движков, потому что для алгоритмов распределения доступны строгие доказательства их корректности, обычно при условии, что входные случайные числа распределены (действительно) равномерно. Например, известно по крайней мере несколько алгоритмов для получения нормально распределенных случайных чисел из равномерно распределенных. Какой из них наиболее эффективен, зависит, по крайней мере, от относительных скоростей выполнения для различных трансцендентных функций, кэширования и поведения процессора при прогнозировании ветвлений и желаемого использования памяти. Таким образом, это предложение оставляет выбор алгоритма за реализацией. Отсюда следует, что выходные последовательности для распределений не будут идентичны во всех реализациях. Ожидается, что реализации будут тщательно выбирать алгоритмы для предварительных распределений, поскольку, безусловно, для клиентов будет неожиданностью, если какой-либо дистрибутив выдает разные числа от одной версии реализации к следующей.
Этот момент повторяется в разделе, определяемом реализацией, в котором говорится:
Алгоритмы создания различных дистрибутивов указаны как определяемые реализацией, поскольку для каждого дистрибутива известно огромное разнообразие алгоритмов. У каждого есть свой компромисс с точки зрения скорости, адаптации к новейшим компьютерным архитектурам и использования памяти. Реализация должна документировать свой выбор, чтобы пользователь мог судить, является ли он приемлемым с точки зрения качества.
Комментарии:
1. прекрасно; так что, если важна согласованность между реализациями, нужно идти по пути нестандартных библиотек. Спасибо за соответствующий отрывок из предложения.
2. @Brandon это все, что я смог найти, так что похоже на это. Вы всегда можете поднять этот вопрос в обсуждении стандарта ISO C и посмотреть, есть ли место для изменений.
3. неплохая идея. Что-то вроде выбора между быстрым и стабильным было бы неплохо; мало чем отличается от того, что делается в <cstdint> (хотя и немного запутанно). Еще раз спасибо.