Найти в Дзене
ZDG

Генератор случайных чисел XoShiRo

Данная статья должна относиться к циклу Игра Apple на Rust, но не хочу заостряться на Rust, так как он только доставляет проблем :) Здесь рассмотрим более общий вопрос генерации случайных чисел. Во-первых, практически во всех языках есть функция rand() или вроде того. Она может выдавать диапазон целых или вещественных чисел, который мы затем можем привести к нужному нам диапазону (если сразу так не получилось). В Rust, однако, данная функция не присутствует по умолчанию. Необходимо добавлять в проект внешние ящики (crate) и пользоваться методами оттуда. Надо сказать, методы очень приличные. Например, если написать let x: u32 = rand::random(); то это автоматически вернёт число в диапазоне 32 бит, а если написать let x: u8 = rand::random(); то вернётся число в диапазоне 8 бит. Магия какая-то там происходит, которая зависит от типа целевой переменной. Кроме того, можно получать случайные числа ещё кучей всяких удобных способов, включая диапазоны (min, max), полудиапазоны и даже нечисловые
Оглавление

Данная статья должна относиться к циклу Игра Apple на Rust, но не хочу заостряться на Rust, так как он только доставляет проблем :)

Здесь рассмотрим более общий вопрос генерации случайных чисел.

Во-первых, практически во всех языках есть функция rand() или вроде того. Она может выдавать диапазон целых или вещественных чисел, который мы затем можем привести к нужному нам диапазону (если сразу так не получилось).

В Rust, однако, данная функция не присутствует по умолчанию. Необходимо добавлять в проект внешние ящики (crate) и пользоваться методами оттуда. Надо сказать, методы очень приличные. Например, если написать

let x: u32 = rand::random();

то это автоматически вернёт число в диапазоне 32 бит, а если написать

let x: u8 = rand::random();

то вернётся число в диапазоне 8 бит. Магия какая-то там происходит, которая зависит от типа целевой переменной.

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

И когда я уже хотел это использовать, то случайно почитал описание данного ящика и там было написано, что он вообще-то БОЛЬШОЙ. Ну то есть подключать его к примитивному проекту игры Apple, конечно, можно, но как-то глупо.

Дух старой школы

Оригинальная игра Apple писалась наверняка на ассемблере, и естественно, там не было никакой функции rand(). Значит, генератор случайных чисел надо было реализовывать своими силами.

А что он из себя представляет?

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

Но свойства чисел таковы, что после определённого количества мутаций состояние деградирует – либо стремится к какому-то одинаковому числу, либо часто выдаёт одни числа, а другие никогда не выдаёт, и т.д.

Так что проблема получения качественного генератора с хорошим распределением и длинным циклом совсем не тривиальна.

Я вообще никогда не умел в математику, и поэтому даже понять не берусь, что и как там должно происходить.

Я просто ищу готовые генераторы, которые были написаны и проверены умными людьми :)

XoShiRo

Мало того, я ищу ещё и такие генераторы, которые просто реализовать. Меня совсем не привлекают сотни файлов с десятками зависимостей, которые надо выкачать.

В результате я нашёл алгоритм, который называется XoShiRo, и означает Xor, Shift, Rotate. Это три битовые операции, которые в нём используются.

Ознакомиться с ним можно здесь:

https://prng.di.unimi.it/

Судя по описанию, он неплох, а для такой игры, как Apple, им и подавно можно пользоваться.

Он написан на языке C, и после того как я порезал всё лишнее, получился такой демонстрационный код:

Да, это всё, что нужно. В качестве состояния генератор хранит 4 32-битных числа. Они и подвергаются операциям Xor, Shift, Rotate.

Далее, я переписал этот код на языке Rust. Опять много плевался :) Но вроде получилось:

-2

Так что мне осталось дописать совсем немного кода, и игру я смогу выложить на github.

A после этого у меня начнётся эпопея с программированием звука :)