Випадкові числа на C ++


12

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

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


1
Мені подобається ваше розділення C ++ та сучасних мов.
jcora

2
Можливо, сказати "вищий рівень" було більш доречно.
o0 '.

Я думаю, що це питання належить до
stackoverflow

5
Щодо того, я дав би іншу відповідь, бо не знав би, що це для ігрового двигуна, на відміну, скажімо, від моделювання в Монте-Карло для медикаментозної терапії, і в цьому випадку, не маючи 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:)

1
Просто хотів зауважити, що у файлах, які ви зв'язали, нічого не вказує на те, що вони є загальнодоступними. Те, як діє закон про авторські права, дійсно має чітко зазначити про це, оскільки закон за замовчуванням передбачає "резерв усіх прав". Насправді навіть безпечніше просто використовувати щось на кшталт ліцензії на 2 статті MIT або BSD, оскільки деякі юрисдикції в основному не визнають, що "це є загальнодоступним" як юридично обов'язкове Якщо вам цікаво бачити, як люди використовують ваш код, можливо, варто подбати про це.
Шон Міддлічч

1
@seanmiddleditch: Мені тут зрозуміло. Якщо ви хочете, щоб це було за ліцензією в стилі MIT, я піду під керівництвом SQLite і передаю вам лише $ 1000.

Відсутність, якщо заголовок у коді, що декларує що-небудь (що робить SQLite, iirc), є основною проблемою. Якщо вам все одно, це здорово. Просто давав вам дружню пропозицію.
Шон Міддлічч

1

Ще один RNG, який я раніше використовував для цілей gamedev, - це "невеликий" RNG Боба Дженкінса, описаний тут .

(Він також має RNG з криптографічною силою, який називається ISAAC, але він більший і повільніше, і для ігор не потрібен такий рівень сили.)


1
Це виглядає дорожче, ніж xorshift (4 xors і 3 зміни проти 4 додавання, 6 зрушень, 2 ors і xor), має гірший період і ризикує отримати дуже короткі цикли з певними ініціалізаціями. Це виглядає швидко, але не найшвидше; нормальний період, але ніде не оптимальний; ті ж основні якості розподілу, що і xorshift; Я не бачу причин використовувати його.

Справедливо. Я не знаю достатньо про аналіз RNG, щоб вивчити властивості розподілу та циклу.
Натан Рід
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.