Можно ли запустить генератор случайных чисел (Math.random) в Javascript?
javascript
random
плаксивый
источник
источник
Ответы:
Нет, это не так, но довольно легко написать свой собственный генератор или, что еще лучше, использовать уже существующий. Проверьте: это связанный вопрос .
Также см. Блог Дэвида Бау для получения дополнительной информации о посеве .
источник
ПРИМЕЧАНИЕ. Несмотря на (или, скорее, из-за) краткости и кажущейся элегантности, этот алгоритм ни в коем случае не является высококачественным с точки зрения случайности. Посмотрите, например, те, которые перечислены в этом ответе для лучших результатов.
(Первоначально адаптировано из умной идеи, представленной в комментарии к другому ответу.)
Вы можете установить
seed
любое число, просто избегайте нуля (или любого кратного Math.PI).На мой взгляд, элегантность этого решения обусловлена отсутствием каких-либо «магических» чисел (кроме 10000, которое представляет собой минимальное количество цифр, которое вы должны выбросить, чтобы избежать нечетных шаблонов - смотрите результаты со значениями 10 , 100 , 1000 ). Краткость тоже хороша.
Это немного медленнее, чем Math.random () (в 2 или 3 раза), но я считаю, что это примерно так же быстро, как и любое другое решение, написанное на JavaScript.
источник
Я реализовал ряд хороших, коротких и быстрых функций генератора псевдослучайных чисел (PRNG) в простом JavaScript. Все они могут быть посеяны и предоставлять качественные номера.
Прежде всего, позаботьтесь о правильной инициализации ваших PRNG. Большинство приведенных ниже генераторов не имеют встроенной процедуры генерации начальных значений (для простоты), но принимают одно или несколько 32-битных значений в качестве начального состояния PRNG. Подобные начальные числа (например, простые начальные числа 1 и 2) могут вызывать корреляции в более слабых PRNG, что приводит к тому, что выходные данные имеют сходные свойства (такие как случайно сгенерированные уровни, являющиеся подобными). Чтобы избежать этого, рекомендуется инициализировать PRNG с хорошо распределенным семенем.
К счастью, хеш-функции очень хороши при генерации начальных значений для PRNG из коротких строк. Хорошая хеш-функция будет генерировать очень разные результаты, даже если две строки похожи. Вот пример, основанный на функции микширования MurmurHash3:
Каждый последующий вызов функции возврата из
xmur3
создает новый «случайный» 32-битное значение хэш - функции , которые будут использоваться в качестве затравки в PRNG. Вот как вы можете использовать это:В качестве альтернативы, просто выберите несколько фиктивных данных для заполнения начального числа и продвиньте генератор несколько раз (12-20 итераций), чтобы тщательно перемешать исходное состояние. Это часто наблюдается в ссылочных реализациях PRNG, но это ограничивает число начальных состояний.
Выходные данные этих функций PRNG создают положительное 32-разрядное число (от 0 до 2 32 -1), которое затем преобразуется в число с плавающей запятой в диапазоне от 0 до 1 (0 включительно, 1 исключительно), эквивалентное
Math.random()
, если вы хотите случайные числа из определенного диапазона, прочитайте эту статью на MDN . Если вам нужны только необработанные биты, просто удалите последнюю операцию деления.Еще одна вещь, которую стоит отметить, это ограничения JS. Числа могут представлять только целые числа с разрешением до 53 бит. А при использовании побитовых операций это уменьшается до 32. Это затрудняет реализацию алгоритмов, написанных на C или C ++, которые используют 64-битные числа. Для переноса 64-битного кода требуются прокладки, которые могут существенно снизить производительность. Поэтому для простоты и эффективности я рассмотрел только алгоритмы, в которых используется 32-разрядная математика, поскольку она напрямую совместима с JS.
sfc32 (простой быстрый счетчик)
sfc32 является частью набора для тестирования случайных чисел PractRand (который он, конечно, проходит). sfc32 имеет 128-битное состояние и очень быстр в JS.
Mulberry32
Mulberry32 - это простой генератор с 32-битным состоянием, но он очень быстрый и имеет хорошее качество (автор утверждает, что он прошел все тесты gjrand testing и имеет полный период 32 , но я не проверял).
Я бы порекомендовал это, если вам просто нужен простой, но приличный PRNG и вам не нужны миллиарды случайных чисел (см. « День рождения» ).
xoshiro128 **
По состоянию на май 2018 года, xoshiro128 ** является новым членом семейства Xorshift , от Vigna / Blackman (который также написал xoroshiro, который используется в Chrome). Это самый быстрый генератор, который предлагает 128-битное состояние.
Авторы утверждают, что он хорошо проходит тесты на случайность ( хотя и с оговорками ). Другие исследователи отмечают, что некоторые тесты в TestU01 не проходят (особенно LinearComp и BinaryRank). На практике это не должно вызывать проблем при использовании чисел с плавающей запятой (таких как эти реализации), но может вызывать проблемы, если полагаться на необработанные младшие биты.
JSF (Небольшой пост Дженкинса)
Это JSF или «smallprng» Боба Дженкинса (2007), парня, который создал ISAAC и SpookyHash . Он проходит тесты PractRand и должен быть достаточно быстрым, хотя и не таким быстрым, как SFC.
LCG (он же Lehmer / Park-Miller RNG или MCG)
LCG чрезвычайно быстрый и простой, но качество его случайности настолько низкое, что неправильное использование может вызвать ошибки в вашей программе! Тем не менее, это значительно лучше, чем некоторые ответы, предлагающие использовать
Math.sin
илиMath.PI
! Это однострочник, что приятно :).Эта реализация называется минимальной стандартной ГСЧ, предложенной Пак-Миллером в 1988 и 1993 годах и реализованной в C ++ 11 as
minstd_rand
. Имейте в виду, что это 31-битное состояние (31 бит дает 2 миллиарда возможных состояний, 32 бита - вдвое больше). Это тот самый тип PRNG, который другие пытаются заменить!Это сработает, но я бы не стал использовать его, если вам действительно не нужна скорость и вас не волнует качество случайности (в любом случае, что такое случайность?). Отлично подходит для игрового джема или демо или что-то. LCG страдают от начальных корреляций, поэтому лучше отказаться от первого результата LCG. И если вы настаиваете на использовании LCG, добавление значения приращения может улучшить результаты, но это, вероятно, бесполезное упражнение, когда существуют гораздо лучшие варианты.
Кажется, есть другие множители, предлагающие 32-битное состояние (увеличенное пространство состояний):
Эти значения LCG получены от: P. L'Ecuyer: Таблица линейных конгруэнтных генераторов разных размеров и с хорошей структурой решетки, 30 апреля 1997 г.
источник
seed = (seed * 185852 + 1) % 34359738337
.Math.imul
позволяет ему переполниться, как это было бы при использовании умножения в C на 32-разрядных целых числах. То, что вы предлагаете, - это LCG, использующий весь диапазон целочисленного пространства JS, что, безусловно, также является интересной областью для изучения. :)Нет, но вот простой псевдослучайный генератор, реализация Multiply-with-carry, которую я адаптировал из Википедии (с тех пор удалена):
РЕДАКТИРОВАТЬ: исправил начальную функцию путем сброса m_z. РЕДАКТИРОВАТЬ 2
: Серьезные недостатки реализации были исправлены
источник
seed
Функция не сбрасывает генератор случайных, так какmz_z
переменная изменяется , когдаrandom()
вызывается. Поэтому установитеmz_z = 987654321
(или любое другое значение) вseed
m_w
, а неm_z
. 2) И те,m_w
иm_z
другие изменяются на основе своих предыдущих значений, поэтому он изменяет результат.Алгоритм Антти Сыкэри хорош и короток. Сначала я сделал вариант, который заменил Jathascript Math.random при вызове Math.seed (s), но затем Джейсон заметил, что возвращение функции будет лучше:
Это дает вам еще одну функциональность, которой нет в Javascript: несколько независимых генераторов случайных чисел. Это особенно важно, если вы хотите, чтобы одновременно выполнялось несколько повторяющихся симуляций.
источник
Math.random
, которая позволит вам иметь несколько независимых генераторов, верно?Math.seed(42);
это сбрасывает функцию, так что еслиvar random = Math.seed(42); random(); random();
вы получаете0.70...
, то0.38...
. Если вы сбросите его с помощьюvar random = Math.seed(42);
повторного вызова , то при следующем вызовеrandom()
вы получите0.70...
снова, а в следующий раз -0.38...
снова.random
вместо перезаписи встроенной функции javascript. ПерезаписьMath.random
может привести к тому, что JIST-компилятор не оптимизирует весь ваш код.Пожалуйста, смотрите работы Пьера Л'Экуйера, относящиеся ко времени конца 1980-х и начала 1990-х годов. Есть и другие. Создание (псевдо) генератора случайных чисел самостоятельно, если вы не являетесь экспертом, довольно опасно, поскольку высока вероятность того, что результаты не будут статистически случайными или будут иметь небольшой период. Пьер (и другие) собрал несколько хороших (псевдо) генераторов случайных чисел, которые легко реализовать. Я использую один из его генераторов LFSR.
https://www.iro.umontreal.ca/~lecuyer/myftp/papers/handstat.pdf
Фил Трой
источник
Комбинируя некоторые из предыдущих ответов, это искомая случайная функция, которую вы ищете:
источник
Math.seed(0)()
возвращает0.2322845458984375
иMath.seed(1)()
возвращает0.23228873685002327
. Изменение обоихm_w
и вm_z
соответствии с семенем, кажется, помогает.var m_w = 987654321 + s; var m_z = 123456789 - s;
производит хорошее распределение первых значений с разными семенами.Написать свой псевдослучайный генератор довольно просто.
Предложение Дейва Скотезе полезно, но, как отмечают другие, оно не совсем равномерно распределено.
Однако это не из-за целочисленных аргументов греха. Это просто из-за диапазона греха, который является одномерной проекцией круга. Если бы вместо этого вы взяли угол круга, он был бы равномерным.
Поэтому вместо sin (x) используйте arg (exp (i * x)) / (2 * PI).
Если вам не нравится линейный порядок, смешайте его немного с xor. Фактический фактор тоже не имеет большого значения.
Для генерации n псевдослучайных чисел можно использовать код:
Также обратите внимание, что вы не можете использовать псевдослучайные последовательности, когда необходима реальная энтропия.
источник
Многие люди, которым в наши дни нужен затравочный генератор случайных чисел в Javascript, используют модуль случайного числа Дэвида Бау .
источник
Math.random
нет, но RAN библиотека решает эту проблему. Он имеет почти все дистрибутивы, которые вы можете себе представить, и поддерживает генерацию случайных чисел. Пример:источник
Я написал функцию, которая возвращает засеянное случайное число, он использует Math.sin для длинного случайного числа и использует начальное число для выбора чисел из этого.
Используйте:
он вернет ваш номер, первый параметр - любое строковое значение; твое семя второй параметр - сколько цифр вернет.
источник
Простой подход для фиксированного семени:
источник
Для числа от 0 до 100.
источник
Math.random
таким образом, чтобы при каждом посевеMath.random
с одним и тем же семенем получался один и тот же последовательный ряд случайных чисел. Этот вопрос, скажем так, не о фактическом использовании / демонстрацииMath.random
.