Случайные числа на C ++

12

Недавно я привык к современным языкам, которые включают в себя хороший генератор случайных чисел, который обычно является Mersenne Twister; теперь, когда я вернулся к C ++, я должен решить, что использовать.

Я искал реализации Mersenne Twister и заметил, что их так много: есть ли такая, которая более широко используется и распространена, или я должен выбрать одну, если они все одинаково хороши?

о0' .
источник
1
Мне нравится ваше разделение C ++ и современных языков.
Jcora
2
Может быть, высказывание «более высокий уровень» было более уместным.
о0 '.
Я думаю, что этот вопрос относится к stackoverflow
TravisG
5
На SO я бы дал другой ответ, потому что я не знал бы, что это было для игрового движка, в отличие от, скажем, симуляций Монте-Карло для медицинской терапии, и в этом случае отсутствие 624 измерений случайности может быть смертельным.

Ответы:

19

C ++ 11 включает генератор Mersenne Twister по умолчанию как часть его нового <random>интерфейса. Например, чтобы сгенерировать целые числа равномерно между [-10, 10], используя MT:

std::mt19937 eng; // This is the Mersenne Twister
std:::uniform_int_distribution<int> dist(-10, 10)
for (int i = 0; i < 10; ++i)
    std::cout << dist(eng) << std::endl;

Большая часть этого также доступна в любом компиляторе, предлагающем TR1, хотя имена немного отличаются; std::tr1::mt19937и std::tr1::uniform_int<int>.

Я обычно предостерегаю людей от использования Mersenne Twister. Это нормальный алгоритм, но большая его популярность - это просто маркетинг. 624 измерения случайности - это больше, чем нужно большинству людей, и MT предъявляет относительно жесткие требования к состоянию, и когда он выполняет полную перезапись таблицы, он может разрушить кэш. Я лично неравнодушен к xorshift, которая дает отличные сроки и разумные распределения для всего, что нужно игре, с крошечными требованиями к памяти и процессору.

Я написал (в основном?) C ++ 11-совместимый генератор xorshift - xorshift.hpp , xorshift.cpp - и разместил его в открытом доступе. Вы можете подключить это к любой функции рандомизации C ++ 11, как указано выше:

xorshift eng;
std:::uniform_int_distribution<int> dist(-10, 10)
for (int i = 0; i < 10; ++i)
    std::cout << dist(eng) << std::endl;

источник
5
Да, это тот ответ, который я искал, поэтому я разместил здесь на gamedev:)
o0 '.
1
Просто хотел отметить, что ничто в файлах, на которые вы ссылаетесь, не указывает на то, что они находятся в свободном доступе. То, как действует закон об авторском праве, должно быть четко обозначено, так как закон предполагает «резерв всех прав» по ​​умолчанию. На самом деле даже безопаснее просто использовать что-то вроде лицензии MIT или BSD с 2 пунктами, поскольку некоторые юрисдикции в основном не признают «это в свободном доступе» как юридически обязывающую. Если вы заинтересованы в том, чтобы люди использовали ваш код, возможно, стоит позаботиться об этом.
Шон Миддледич
1
@seanmiddleditch: я проясняю это прямо здесь. Если вы хотите получить лицензию в стиле MIT, я последую примеру SQLite и дам вам его всего за 1000 долларов.
Отсутствие заголовка в коде, декларирующем что-либо (что делает SQLite, iirc), является основной проблемой. Если тебе все равно, это круто. Просто давал тебе дружеское предложение.
Шон Мидлдич
1

Еще одна ГСЧ, которую я использовал ранее для целей gamedev, это «маленькая» ГСБ Боба Дженкинса, описанная здесь .

(У него также есть криптографический RNG под названием ISAAC, но он больше и медленнее, и играм не нужен такой уровень силы.)

Натан Рид
источник
1
Это выглядит дороже, чем xorshift (4 xors и 3 сдвига против 4 сложений, 6 сдвигов, 2 ors и xor), имеет худший период и подвергается риску очень коротких циклов с некоторыми инициализациями. Это выглядит быстро, но не быстрее; период хорошо, но далеко не оптимальный; те же основные качества распределения, что и в xorshift; Я не вижу причин использовать это.
Справедливо. Я не знаю достаточно об анализе ГСЧ, чтобы копаться в свойствах распределения и цикла.
Натан Рид