Понимание "случайности"

Я не могу обдумать это, что является более случайным?

rand()

ИЛИ ЖЕ

rand() * rand()

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

РЕДАКТИРОВАТЬ:

Интуитивно я знаю, что математический ответ будет состоять в том, что они одинаково случайны, но я не могу не думать, что если вы дважды "запустите алгоритм случайных чисел", когда вы умножите их вдвоем, вы создадите нечто более случайное, чем просто это один раз.

28 ответов

Решение

Просто уточнение

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

пример

Это образец равномерного случайного распределения, смоделированный с помощью псевдослучайной переменной:

Гистограмма Случайности

        BarChart[BinCounts[RandomReal[{0, 1}, 50000], 0.01]]

Хотя это распределение вы получите после умножения двух случайных величин:

Гистограмма Случайного () * Случайного

        BarChart[BinCounts[Table[RandomReal[{0, 1}, 50000] * 
                                 RandomReal[{0, 1}, 50000], {50000}], 0.01]]

Итак, оба являются "случайными", но их распределение сильно отличается.

Другой пример

В то время как 2 * Random() распределяется равномерно:

Гистограмма 2 * Случайная

        BarChart[BinCounts[2 * RandomReal[{0, 1}, 50000], 0.01]]

Случайный () + Случайный () нет!

Гистограмма случайных () + случайных

        BarChart[BinCounts[Table[RandomReal[{0, 1}, 50000] + 
                                 RandomReal[{0, 1}, 50000], {50000}], 0.01]]

Центральная предельная теорема

Центральная предельная теорема утверждает, что сумма Random() стремится к нормальному распределению при увеличении членов.

Всего четыре условия:

Гистограмма случайных () + случайных () + случайных () + случайных

BarChart[BinCounts[Table[RandomReal[{0, 1}, 50000] + RandomReal[{0, 1}, 50000] +
                   Table[RandomReal[{0, 1}, 50000] + RandomReal[{0, 1}, 50000],
                   {50000}],
         0.01]]  

И здесь вы можете увидеть путь от равномерного к нормальному распределению, сложив 1, 2, 4, 6, 10 и 20 равномерно распределенных случайных величин:

Добавлена ​​гистограмма разных чисел случайных величин

редактировать

Несколько кредитов

Спасибо Thomas Ahle за то, что он указал в комментариях, что распределения вероятностей, показанные на последних двух изображениях, известны как распределение Ирвина-Холла.

Спасибо sven за ее замечательную порванную функцию

Я полагаю, что оба метода случайны, хотя мой читатель сказал бы, что rand() * rand() является менее случайным, потому что это даст больше нулей. Как только один rand() является 0Итого становится 0

Ни один из них не является "более случайным".

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

На вопрос, уменьшит ли это коллизии, ответ - нет. Это фактически увеличит столкновения из-за эффекта умножения двух чисел, где 0 < n < 1, Результатом будет меньшая доля, что приведет к смещению результата к нижнему краю спектра.

Некоторые дальнейшие объяснения. В дальнейшем "непредсказуемый" и "случайный" относятся к способности кого-либо угадывать, какое следующее число будет основано на предыдущих числах, т.е. оракул.

Данное семя x который генерирует следующий список значений:

0.3, 0.6, 0.2, 0.4, 0.8, 0.1, 0.7, 0.3, ...

rand() сгенерирует приведенный выше список, и rand() * rand() сгенерирует:

0.18, 0.08, 0.08, 0.21, ...

Оба метода всегда будут создавать один и тот же список чисел для одного и того же начального числа и, следовательно, одинаково предсказуемы оракулом. Но если вы посмотрите на результаты умножения двух вызовов, вы увидите, что все они находятся под 0.3 несмотря на приличное распределение в оригинальной последовательности. Числа смещены из-за эффекта умножения двух фракций. Результирующее число всегда меньше, поэтому вероятность столкновения гораздо выше, хотя все еще непредсказуема.

Упрощение, чтобы проиллюстрировать точку.

Предположим, ваша случайная функция только выводит 0 или же 1,

random() один из (0,1), но random()*random() один из (0,0,0,1)

Вы можете четко видеть, что шансы получить 0 во втором случае ни в коем случае не равны тем, чтобы получить 1,


Когда я впервые опубликовал этот ответ, я хотел, чтобы он был как можно более коротким, чтобы человек, читающий его, сразу понял разницу между random() а также random()*random(), но я не могу удержаться от ответа на оригинальный вопрос ad litteram:

Что является более случайным?

Быть тем random(), random()*random(), random()+random(), (random()+1)/2 или любая другая комбинация, которая не приводит к фиксированному результату, имеет тот же источник энтропии (или одинаковое начальное состояние в случае псевдослучайных генераторов), ответом будет то, что они одинаково случайны (разница заключается в их распределении), Прекрасный пример, на который мы можем посмотреть, это игра в кости. Число, которое вы получите, будет random(1,6)+random(1,6) и мы все знаем, что получение 7 имеет наибольший шанс, но это не означает, что результат броска двух кубиков более или менее случайен, чем результат броска одного.

Вот простой ответ. Рассмотрим монополию. Вы бросаете два шестигранных кубика (или 2d6 для тех, кто предпочитает игровую нотацию) и берете их сумму. Наиболее распространенный результат - 7, потому что есть 6 возможных способов бросить 7 (1,6 2,5 3,4 4,3 5,2 и 6,1). Тогда как 2 можно бросить только на 1,1. Легко видеть, что бросок 2d6 отличается от броска 1d12, даже если диапазон одинаков (игнорируя, что вы можете получить 1 на 1d12, точка остается прежней). Умножение ваших результатов вместо их добавления приведет к искажению их аналогичным образом, при этом большинство ваших результатов будет находиться в середине диапазона. Если вы пытаетесь уменьшить выбросы, это хороший метод, но он не поможет сделать равномерное распределение.

(И как ни странно, это также увеличит низкие броски. Предполагая, что ваша случайность начинается с 0, вы увидите всплеск в 0, потому что он превратит любой другой бросок в 0. Рассмотрим два случайных числа от 0 до 1 (включительно).) и умножение. Если один из результатов равен 0, то все становится равным 0 независимо от другого результата. Единственный способ получить 1 из этого - это сделать оба броска равными 1. На практике это, вероятно, не имеет значения но это делает для странного графика.)

Обязательный xkcd...
возврат 4; // выбрано по броску костей, гарантированно будет случайным.

Это может помочь думать об этом в более дискретных цифрах. Подумайте, хотите ли вы генерировать случайные числа от 1 до 36, поэтому вы решаете, что самый простой способ - бросить два честных шестигранных кубика. Вы получаете это:

     1    2    3    4    5    6
  -----------------------------
1|   1    2    3    4    5    6
2|   2    4    6    8   10   12
3|   3    6    9   12   15   18
4|   4    8   12   16   20   24   
5|   5   10   15   20   25   30
6|   6   12   18   24   30   36

Таким образом, у нас есть 36 чисел, но не все они представлены в достаточной степени, а некоторые вообще не встречаются. Числа около центральной диагонали (от нижнего левого угла к верхнему правому углу) будут появляться с наибольшей частотой.

Те же принципы, которые описывают несправедливое распределение между кубиками, в равной степени применимы к числам с плавающей запятой между 0,0 и 1,0.

Некоторые вещи о "случайности" нелогичны.

Предполагая равномерное распределение rand(), следующее даст вам неплоские распределения:

  • высокий уклон: sqrt(rand(range^2))
  • пик смещения в середине: (rand(range) + rand(range))/2
  • низкое: смещение: range - sqrt(rand(range^2))

Есть много других способов создания определенных кривых смещения. Я сделал быструю проверку rand() * rand() и это дает вам очень нелинейное распределение.

Большинство реализаций rand() имеют некоторый период. Т.е. после какого-то колоссального количества вызовов последовательность повторяется. Последовательность выходов rand() * rand() повторяется в половине случаев, так что это "менее случайный" в этом смысле.

Кроме того, без тщательной конструкции выполнение арифметики со случайными значениями приводит к меньшей случайности. Плакат выше цитируетсяrand() + rand() + rand()... "(скажем, k раз), которое на самом деле будет стремиться в k раз увеличить среднее значение диапазона значений rand() возвращается. (Это случайная прогулка с шагами, симметричными относительно этого значения.)

Предположим для конкретности, что ваша функция rand() возвращает равномерно распределенное случайное действительное число в диапазоне [0,1). (Да, этот пример допускает бесконечную точность. Это не изменит результат.) Вы не выбрали конкретный язык, и разные языки могут делать разные вещи, но следующий анализ выполняется с модификациями для любой не извращенной реализации rand(). Продукт rand() * rand() также находится в диапазоне [0,1), но больше не является равномерно распределенным. Фактически, произведение с такой же вероятностью будет в интервале [0,1/4), как и в интервале [1/4,1). Дальнейшее умножение приведет к смещению результата еще дальше к нулю. Это делает результат более предсказуемым. В широких мазках, более предсказуемо == менее случайно.

Практически любая последовательность операций с равномерно случайным вводом будет неравномерно случайной, что приведет к повышению предсказуемости. С осторожностью можно преодолеть это свойство, но тогда было бы легче сгенерировать равномерно распределенное случайное число в диапазоне, который вы на самом деле хотели, чем тратить время на арифметику.

"случайный" или "более случайный" - это все равно, что спросить, какой ноль больше нулевой.

В этом случае, rand это PRNG, так что не совсем случайно. (на самом деле, вполне предсказуемо, если семя известно). Умножение его на другое значение делает его не более или менее случайным.

Истинный RNG крипто-типа на самом деле будет случайным. И запуск значений через какую-либо функцию не может добавить к ней больше энтропии и, скорее всего, удалит энтропию, сделав ее более случайной.

Концепция, которую вы ищете, это "энтропия", "степень" беспорядка цепочки битов. Идея легче всего понять с точки зрения понятия "максимальная энтропия".

Приблизительное определение строки битов с максимальной энтропией состоит в том, что она не может быть выражена точно в виде более короткой строки битов (т. Е. С использованием некоторого алгоритма, чтобы расширить меньшую строку обратно в исходную строку).

Соответствие максимальной энтропии случайности связано с тем фактом, что если вы выберете число "случайно", вы почти наверняка выберете число, битовая строка которого близка к максимальной энтропии, то есть оно не может быть сжато. Это наше лучшее понимание того, что характеризует "случайное" число.

Итак, если вы хотите сделать случайное число из двух случайных выборок, которое "вдвое" случайнее, вы должны объединить две строки битов вместе. Практически, вы просто поместите образцы в верхнюю и нижнюю половинки слова двойной длины.

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

Принятый ответ довольно приятный, но есть и другой способ ответить на ваш вопрос. Ответ PachydermPuncher уже использует этот альтернативный подход, и я просто собираюсь его немного расширить.

Самый простой способ думать об информационной теории - это наименьшая единица информации, один бит.

В стандартной библиотеке C rand() возвращает целое число в диапазоне от 0 до RAND_MAX, предел, который может быть определен по-разному в зависимости от платформы. предполагать RAND_MAX случается, определяется как 2^n - 1 где n является некоторым целым числом (это происходит в реализации Microsoft, где n 15). Тогда мы бы сказали, что хорошая реализация вернется n биты информации.

Представь это rand() создает случайные числа, подбрасывая монету, чтобы найти значение одного бита, и затем повторяя ее, пока она не получит пакет из 15 бит. Тогда биты являются независимыми (значение любого одного бита не влияет на вероятность того, что другие биты в той же партии имеют определенное значение). Таким образом, каждый бит, рассматриваемый независимо, подобен случайному числу от 0 до 1 включительно и "равномерно распределен" по этому диапазону (с вероятностью 0 к 1).

Независимость битов гарантирует, что числа, представленные пакетами битов, также будут равномерно распределены по их диапазону. Это интуитивно очевидно: если есть 15 битов, допустимый диапазон от нуля до 2^15 - 1 = 32767. Каждое число в этом диапазоне представляет собой уникальный набор битов, например:

010110101110010

и если биты независимы, то ни один шаблон не будет более вероятным, чем любой другой шаблон. Таким образом, все возможные числа в диапазоне одинаково вероятны. И поэтому верно обратное: если rand() производит равномерно распределенные целые числа, тогда эти числа состоят из независимых битов.

Так что подумайте о rand() как производственная линия для изготовления битов, которые просто служат для их производства партиями произвольного размера. Если вам не нравится размер, разбейте партии на отдельные биты, а затем соедините их вместе в любых количествах, которые вам нравятся (хотя, если вам нужен определенный диапазон, который не является степенью 2, вам нужно уменьшить свои числа и, безусловно, самый простой способ сделать это - преобразовать в плавающую точку).

Возвращаясь к исходному предложению, предположим, что вы хотите перейти от партий 15 к партиям 30, спросите rand() для первого числа сдвиньте его на 15 позиций, затем добавьте еще одно rand() к этому. Это способ объединить два звонка rand() не нарушая равномерное распределение. Это работает просто потому, что нет совпадений между местами, где вы размещаете биты информации.

Это очень отличается от "растяжения" диапазона rand() умножая на константу. Например, если вы хотите удвоить диапазон rand() Вы могли бы умножить на два - но теперь вы получите только четные числа, а не нечетные! Это не совсем гладкое распределение и может быть серьезной проблемой в зависимости от приложения, например, игра в рулетку, якобы допускающая нечетные / четные ставки. (Думая в терминах битов, вы избежите этой ошибки интуитивно, потому что вы поймете, что умножение на два - это то же самое, что смещение битов влево (большее значение) на одно место и заполнение пробела нулем. Таким образом, очевидно, что объем информации одинаков - она ​​просто немного изменилась.)

Такие пропуски в диапазонах чисел нельзя охватить в приложениях с числами с плавающей запятой, потому что диапазоны с плавающей запятой по своей природе имеют пробелы, которые просто не могут быть представлены вообще: бесконечное число пропущенных действительных чисел существует в промежутке между каждыми двумя представимыми плавающими номера точек! Так что нам просто нужно научиться жить с пробелами в любом случае.

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

Но, по крайней мере, если вы думаете, что это кусочки, ваша интуиция может продвинуть вас немного дальше. Биты действительно легки - даже компьютеры могут их понять.

Как уже говорили другие, простой короткий ответ: нет, это не более случайный, но это меняет распределение.

Предположим, вы играли в игру в кости. У вас есть совершенно честные, случайные кости. Будут ли броски кубиков "более случайными", если перед каждым броском кубиков вы сначала кладете две кубики в миску, встряхиваете их, выбираете одну из кубиков наугад, а затем бросаете ее? Понятно, что это не имеет значения. Если оба кубика дают случайные числа, то случайный выбор одного из двух кубиков не будет иметь значения. В любом случае вы получите случайное число от 1 до 6 с равномерным распределением по достаточному количеству бросков.

Я полагаю, что в реальной жизни такая процедура может быть полезна, если вы подозреваете, что игра в кости НЕ будет справедливой. Если, скажем, игральные кости слегка несбалансированы, так что один имеет тенденцию давать 1 чаще, чем 1/6 времени, а другой имеет тенденцию давать 6 необычно часто, то случайный выбор между этими двумя, как правило, скрывает смещение. (Хотя в этом случае 1 и 6 все равно будут больше, чем 2, 3, 4 и 5. Ну, я думаю, в зависимости от характера дисбаланса.)

Есть много определений случайности. Одно из определений случайного ряда состоит в том, что это ряд чисел, созданный случайным процессом. По этому определению, если я брошу честный кубик 5 раз и получу числа 2, 4, 3, 2, 5, то это случайный ряд. Если я затем бросаю ту же самую справедливую кубик еще 5 раз и получаю 1, 1, 1, 1, 1, то это тоже случайный ряд.

Несколько авторов указали, что случайные функции на компьютере не являются действительно случайными, а скорее псевдослучайными, и что если вы знаете алгоритм и начальное число, они полностью предсказуемы. Это правда, но большую часть времени совершенно не имеет значения. Если я перемешаю колоду карт и переворачиваю их по одной за раз, это должен быть случайный ряд. Если кто-то посмотрит на карты, результат будет полностью предсказуемым, но по большинству определений случайности это не сделает его менее случайным. Если серия проходит статистические тесты на случайность, то, что я заглянул в карты, не изменит этого факта. На практике, если мы разыгрываем большие суммы денег на вашей способности угадать следующую карту, то тот факт, что вы заглянули в карты, очень важен. Если мы используем серию для имитации выбора меню посетителями нашего веб-сайта с целью проверки производительности системы, то тот факт, что вы заглянули, не будет иметь никакого значения. (Пока вы не модифицируете программу, чтобы воспользоваться этими знаниями.)

РЕДАКТИРОВАТЬ

Я не думаю, что смогу прокомментировать мой ответ на проблему Монти Холла, поэтому я обновлю свой ответ.

Для тех, кто не читал ссылку Велисария, суть ее заключается в следующем: участнику игрового шоу предоставляется выбор из 3 дверей. За одним стоит ценный приз, за ​​остальными - что-то бесполезное. Он выбирает дверь № 1. Прежде чем показать, является ли он победителем или проигравшим, хозяин открывает дверь #3, чтобы показать, что он проигравший. Затем он дает участнику возможность перейти к двери № 2. Должен ли участник сделать это или нет?

Ответ, который оскорбляет интуицию многих людей, состоит в том, что он должен переключиться. Вероятность того, что его исходный выбор был победителем, равна 1/3, а другая дверь - победителем - 2/3. Моя первоначальная интуиция, как и у многих других людей, заключается в том, что переключение не принесет никакой выгоды, что шансы только что были изменены на 50:50.

В конце концов, предположим, что кто-то включил телевизор сразу после того, как хозяин открыл утраченную дверь. Этот человек увидит две оставшиеся закрытые двери. Предполагая, что он знает природу игры, он сказал бы, что есть шанс 1/2, что каждая дверь скрывает приз. Как шансы для зрителя могут быть 1/2: 1/2, а шансы для участника - 1/3: 2/3?

Я действительно должен был думать об этом, чтобы превратить мою интуицию в форму. Чтобы разобраться с этим, поймите, что когда мы говорим о вероятностях в такой проблеме, мы подразумеваем вероятность, которую вы назначаете с учетом доступной информации. Для члена команды, который поставил приз, скажем, за дверью № 1, вероятность того, что приз находится за дверью № 1, составляет 100%, а вероятность того, что он находится за любой из двух других дверей, равна нулю.

Шансы члена экипажа отличаются от шансов участника, потому что он знает то, чего не знает участник, а именно, за какой дверью он поставил приз. Аналогично, шансы претендента отличаются от шансов зрителя, потому что он знает то, чего не знает зритель, а именно, какую дверь он первоначально выбрал. Это не имеет значения, потому что выбор хозяина, какую дверь открыть, не случаен. Он не откроет дверь, которую выбрал участник, и не откроет дверь, которая скрывает приз. Если это одна и та же дверь, это оставляет ему два выбора. Если это разные двери, то остается только одна.

Итак, как мы можем придумать 1/3 и 2/3? Когда участник первоначально выбрал дверь, он имел 1/3 шанса выбрать победителя. Я думаю, что многое очевидно. Это означает, что был шанс 2/3, что одна из других дверей станет победителем. Если хозяин игры ему предоставит возможность переключаться без предоставления какой-либо дополнительной информации, выигрыша не будет. Опять же, это должно быть очевидно. Но один из способов взглянуть на это - сказать, что есть шанс 2/3, что он выиграет, переключившись. Но у него есть 2 альтернативы. Таким образом, у каждого есть только 2/3, деленное на 2 = 1/3 шанса стать победителем, что не лучше, чем его первоначальный выбор. Конечно, мы уже знали конечный результат, это просто вычисляет его по-другому.

Но теперь ведущий показывает, что один из этих двух вариантов не является победителем. Так что из 2/3 шансов, что дверь, которую он не выбрал, является победителем, он теперь знает, что 1 из 2 альтернатив не так. Другой может или не может быть. Таким образом, у него больше нет 2/3, деленного на 2. У него есть ноль для открытой двери и 2/3 для закрытой двери.

Представьте, что у вас есть простая проблема с подбрасыванием монет, когда четные считаются головами, а нечетные - хвостами. Логическая реализация:

rand() mod 2

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

Теперь рассмотрим небольшой твик:

rand() * rand() mod 2

Если один из результатов является четным, то весь результат должен быть четным. Рассмотрим 4 возможных результата (четное * четное = четное, четное * нечетное = четное, нечетное * четное = четное, нечетное * нечетное = нечетное). Теперь, при достаточно большом распределении, ответ должен быть даже в 75% случаев.

Я бы поставил головы на твоем месте.

Этот комментарий действительно больше объясняет, почему вы не должны реализовывать пользовательскую случайную функцию, основанную на вашем методе, чем обсуждение математических свойств случайности.

Если вы сомневаетесь в том, что произойдет с комбинациями ваших случайных чисел, вы можете использовать уроки, которые вы извлекли из теории статистики.

В ситуации ОП он хочет знать, каков результат X*X = X^2, где X - случайная величина, распределенная вдоль Uniform[0,1]. Мы будем использовать технику CDF, так как это только однозначное сопоставление.

Так как X ~ Uniform[0,1], это cdf: fX(x) = 1 Мы хотим преобразование Y<- X ^ 2, таким образом, y = x ^ 2 Найдите обратное x (y): sqrt (y) = x это дает нам х в зависимости от у. Затем найдите производную dx / dy: d / dy (sqrt (y)) = 1/(2 sqrt(y))

Распределение Y задается как: fY(y) = fX(x (y)) | dx / dy | = 1 / (2 кв. (У))

Мы еще не закончили, нам нужно получить домен Y. так как 0 <= x < 1, 0 <= x^2 < 1, поэтому Y находится в диапазоне [0, 1). Если вы хотите проверить, действительно ли pdf-файл Y является pdf, интегрируйте его по домену: интегрируйте 1/(2 sqrt(y)) от 0 до 1, и, действительно, он появляется как 1. Также обратите внимание на форму Эта функция выглядит так, как будто она написана.

Что касается таких вещей, как X1 + X2 +... + Xn(где Xi ~ Uniform [0,1]), мы можем просто обратиться к центральной предельной теореме, которая работает для любого распределения, моменты которого существуют. Вот почему Z-тест существует на самом деле.

Другие методы определения результирующего pdf включают преобразование Якоби (которое является обобщенной версией метода cdf) и метод MGF.

РЕДАКТИРОВАТЬ: В качестве пояснения, обратите внимание, что я говорю о распределении результирующего преобразования, а не его случайности. Это на самом деле для отдельного обсуждения. Также то, что я на самом деле получил, было для (rand())^2. Для rand() * rand() это намного сложнее, что, в любом случае, не приведет к равномерному распределению любого рода.

Это не совсем очевидно, но rand() как правило, более случайный, чем rand()*rand(), Важно то, что на самом деле это не очень важно для большинства применений.

Но, во-первых, они производят разные дистрибутивы. Это не проблема, если вы этого хотите, но это имеет значение. Если вам нужен конкретный дистрибутив, тогда проигнорируйте весь вопрос "который является более случайным". Так почему же rand() более случайным?

Суть почему rand() более случайным (при условии, что он генерирует случайные числа с плавающей запятой с диапазоном [0..1], что очень распространено) в том, что когда вы умножаете два числа FP вместе с большим количеством информации в мантиссе, вы получаете некоторая потеря информации с конца; в поплавке двойной точности IEEE просто недостаточно битов, чтобы хранить всю информацию, которая была в двух поплавках двойной точности IEEE, равномерно случайным образом выбранную из [0..1], и эти дополнительные биты информации теряются. Конечно, это не имеет большого значения, так как вы (вероятно) не собирались использовать эту информацию, но потеря реальна. Также не имеет значения, какой дистрибутив вы производите (т. Е. Какую операцию вы используете для комбинации). Каждое из этих случайных чисел содержит (в лучшем случае) 52 бита случайной информации - это то, что может содержать двойник IEEE - и если вы объедините два или более в одно, вы все равно будете иметь не более 52 бит случайной информации.

В большинстве случаев использование случайных чисел не использует даже столько случайности, сколько фактически доступно в случайном источнике. Получите хороший PRNG и не беспокойтесь об этом. (Уровень "добродетели" зависит от того, что вы делаете с ним; вы должны быть осторожны при симуляции или криптографии Монте-Карло, но в противном случае вы, вероятно, можете использовать стандартный PRNG, поскольку это обычно намного быстрее.)

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

Если на дисплее вашего компьютера отображается 16 цифр rand() было бы сказать 0,124567890123, умноженное на секунду rand(), 0.1234567890123, даст 0,0152415 то, что вы определенно найдете меньше решений, если бы повторили эксперимент 10^14 раз.

Как правило, плавающие случайные числа основаны на алгоритме, который выдает целое число от нуля до определенного диапазона. Таким образом, используя rand()*rand(), вы, по сути, говорите int_rand()*int_rand()/rand_max^2 - то есть исключаете любое простое число / rand_max^2.

Это значительно меняет рандомизированное распределение.

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

Большинство этих распределений происходит потому, что вы должны ограничить или нормализовать случайное число.

Мы нормализуем его, чтобы оно было положительным, соответствовало диапазону и даже соответствовало ограничениям объема памяти для назначенного типа переменной.

Другими словами, поскольку мы должны ограничить случайный вызов между 0 и X (X является пределом размера нашей переменной), у нас будет группа "случайных" чисел от 0 до X.

Теперь, когда вы добавляете случайное число к другому случайному числу, сумма будет где-то между 0 и 2X... это отклоняет значения от краевых точек (вероятность сложения двух маленьких чисел вместе и двух больших чисел очень мала, когда у вас есть два случайных числа в большом диапазоне).

Вспомните случай, когда у вас было число, близкое к нулю, и вы добавляете его к другому случайному числу, оно, безусловно, будет больше и будет отличаться от 0 (это будет справедливо для больших чисел, а также маловероятно, что у вас будет два больших числа). (числа, близкие к X), возвращаемые функцией Random дважды.

Теперь, если вы установите случайный метод с отрицательными числами и положительными числами (одинаково охватывающими нулевую ось), это больше не будет иметь место.

Скажем например RandomReal({-x, x}, 50000, .01) тогда вы получите равномерное распределение чисел на отрицательной и положительной стороне, и если вы сложите случайные числа вместе, они сохранят свою "случайность".

Теперь я не уверен, что случилось бы с Random() * Random() с отрицательным и положительным диапазоном... это был бы интересный график, но я должен вернуться к написанию кода сейчас.:-П

  1. Там нет такой вещи, как более случайным. Это либо случайно, либо нет. Случайный означает "трудно предсказать". Это не означает недетерминированность. Random() и random() * random() одинаково случайны, если random() является случайным. Распределение не имеет отношения к случайности. Если происходит неравномерное распределение, это просто означает, что некоторые значения более вероятны, чем другие; они все еще непредсказуемы.

  2. Поскольку речь идет о псевдослучайности, числа очень детерминированы. Однако псевдослучайность часто бывает достаточной в вероятностных моделях и симуляциях. Хорошо известно, что усложнение генератора псевдослучайных чисел усложняет его анализ. Вряд ли это улучшит случайность; это часто приводит к провалу статистических тестов.

  3. Важны желаемые свойства случайных чисел: повторяемость и воспроизводимость, статистическая случайность, (обычно) равномерно распределенная, и большой период - несколько.

  4. Относительно преобразований случайных чисел. Как кто-то сказал, сумма двух или более равномерно распределенных приводит к нормальному распределению. Это аддитивная центральная предельная теорема. Он применяется независимо от исходного распределения, если все распределения независимы и идентичны. Мультипликативная центральная предельная теорема говорит, что произведение двух или более независимых и одинаково распределенных случайных величин является логнормальным. График, созданный кем-то еще, выглядит экспоненциально, но он действительно логнормален. Таким образом, random() * random() логнормально распределен (хотя он не может быть независимым, так как числа извлекаются из одного потока). Это может быть желательно в некоторых приложениях. Однако обычно лучше генерировать одно случайное число и преобразовывать его в логически-распределенное число. Random() * random() может быть сложным для анализа.

Для получения дополнительной информации обратитесь к моей книге на www.performorama.org. Книга находится в стадии разработки, но соответствующий материал есть. Обратите внимание, что номера глав и разделов могут меняться со временем. Глава 8 (теория вероятностей) - разделы 8.3.1 и 8.3.3, глава 10 (случайные числа).

На самом деле, когда вы думаете об этом rand() * rand() менее случайно, чем rand(), Вот почему

По сути, число нечетных чисел равно количеству четных чисел. И говоря, что 0,04325 нечетно, а 0,388 четно, 0,4 - четно, 0,15 нечетно,

Это означает, что rand() имеет равный шанс быть четным или нечетным десятичным числом.

С другой стороны, rand() * rand() шансы сложены немного по-другому. Скажем так:

double a = rand();
double b = rand();
double c = a * b;

a а также b оба имеют 50% вероятности быть четными или нечетными. Знаю это

  • даже * даже = даже
  • четный * нечетный = четный
  • нечетный * нечетный = нечетный
  • нечетный * четный = четный

означает, что есть 75% вероятность того, что c четный, в то время как только 25% вероятность, что это странно, делает значение rand() * rand() более предсказуемо, чем rand()следовательно, менее случайный.

Мы можем сравнить два массива чисел относительно случайности, используя сложность Колмогорова. Если последовательность чисел не может быть сжата, то это самое случайное, что мы можем достичь на этой длине... Я знаю, что этот тип измерения является более теоретическим вариант...

Используйте регистр сдвига с линейной обратной связью (LFSR), который реализует примитивный полином.

Результатом будет последовательность из 2^n псевдослучайных чисел, т.е. ни одно из них не повторяется в последовательности, где n - это число битов в LFSR ...., что приводит к равномерному распределению.

http://en.wikipedia.org/wiki/Linear_feedback_shift_register http://www.xilinx.com/support/documentation/application_notes/xapp052.pdf

Используйте "случайное" начальное число на основе микросекунд часов вашего компьютера или, возможно, подмножество результата md5 для некоторых постоянно меняющихся данных в вашей файловой системе.

Например, 32-битный LFSR сгенерирует 2^32 уникальных числа в последовательности (без 2 одинаковых), начиная с заданного начального числа. Последовательность всегда будет в том же порядке, но отправная точка будет отличаться (очевидно) для разных семян. Таким образом, если возможно повторяющаяся последовательность между посевами не является проблемой, это может быть хорошим выбором.

Я использовал 128-битные LFSR для генерации случайных тестов в аппаратных симуляторах с использованием начального числа, которое представляет собой результат md5 для постоянно меняющихся системных данных.

При условии, что rand() возвращает число между [0, 1) Очевидно, что rand() * rand() будет смещен к 0. Это потому, что умножение x на число между [0, 1) приведет к числу меньше x, Вот распределение еще 10000 случайных чисел:

google.charts.load("current", { packages: ["corechart"] });
google.charts.setOnLoadCallback(drawChart);

function drawChart() {
  var i;
  var randomNumbers = [];
  for (i = 0; i < 10000; i++) {
    randomNumbers.push(Math.random() * Math.random());
  }
  var chart = new google.visualization.Histogram(document.getElementById("chart-1"));
  var data = new google.visualization.DataTable();
  data.addColumn("number", "Value");
  randomNumbers.forEach(function(randomNumber) {
    data.addRow([randomNumber]);
  });
  chart.draw(data, {
    title: randomNumbers.length + " rand() * rand() values between [0, 1)",
    legend: { position: "none" }
  });
}
<script src="https://www.gstatic.com/charts/loader.js"></script>

<div id="chart-1" style="height: 500px">Generating chart...</div>

Если rand() возвращает целое число между [x, y] тогда у вас есть следующий дистрибутив. Обратите внимание на количество нечетных и четных значений:

google.charts.load("current", { packages: ["corechart"] });
google.charts.setOnLoadCallback(drawChart);
document.querySelector("#draw-chart").addEventListener("click", drawChart);

function randomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

function drawChart() {
  var min = Number(document.querySelector("#rand-min").value);
  var max = Number(document.querySelector("#rand-max").value);
  if (min >= max) {
    return;
  }
  var i;
  var randomNumbers = [];
  for (i = 0; i < 10000; i++) {
    randomNumbers.push(randomInt(min, max) * randomInt(min, max));
  }
  var chart = new google.visualization.Histogram(document.getElementById("chart-1"));
  var data = new google.visualization.DataTable();
  data.addColumn("number", "Value");
  randomNumbers.forEach(function(randomNumber) {
    data.addRow([randomNumber]);
  });
  chart.draw(data, {
    title: randomNumbers.length + " rand() * rand() values between [" + min + ", " + max + "]",
    legend: { position: "none" },
    histogram: { bucketSize: 1 }
  });
}
<script src="https://www.gstatic.com/charts/loader.js"></script>

<input type="number" id="rand-min" value="0" min="0" max="10">
<input type="number" id="rand-max" value="9" min="0" max="10">
<input type="button" id="draw-chart" value="Apply">

<div id="chart-1" style="height: 500px">Generating chart...</div>

Легко показать, что сумма двух случайных чисел не обязательно случайна. Представьте, что у вас есть 6-ти сторонний кубик. Каждый номер имеет 1/6 шанс появления. Теперь скажите, что у вас было 2 кубика и подвели итоги. Распределение этих сумм не 1/12. Зачем? Потому что одни цифры появляются больше, чем другие. Есть несколько разделов из них. Например, число 2 является суммой только 1+1, но 7 может быть сформировано 3+4 или 4+3 или 5+2 и т. Д., Так что у него больше шансов на успех.

Поэтому, применяя преобразование, в этом случае добавление к случайной функции не делает ее более случайной или обязательно сохраняет случайность. В случае вышеупомянутой игры в кости, распределение искажено до 7 и, следовательно, менее случайно.

Итак, я постараюсь добавить какое-то значение, чтобы дополнить ответы других, говоря, что вы создаете и используете генератор случайных чисел.

Генераторы случайных чисел - это устройства (в очень общем смысле), которые имеют множество характеристик, которые могут быть изменены для соответствия цели. Некоторые из них (от меня):

  • Энтропия: как в энтропии Шеннона
  • Распределение: статистическое распределение (пуассоновское, нормальное и т. Д.)
  • Тип: что является источником чисел (алгоритм, естественное событие, комбинация и т. Д.) И применяемый алгоритм.
  • Эффективность: быстрота или сложность исполнения.
  • Шаблоны: периодичность, последовательности, прогоны и т. Д.
  • и, вероятно, больше...

В большинстве ответов здесь распределение является основной точкой интереса, но, смешивая и сопоставляя функции и параметры, вы создаете новые способы генерирования случайных чисел, которые будут иметь различные характеристики, для некоторых из которых оценка может быть неочевидной на первый взгляд.

Как уже отмечали другие, на этот вопрос трудно ответить, так как у каждого из нас есть своя картина случайности в его голове.

Вот почему я настоятельно рекомендую вам потратить некоторое время и прочитать этот сайт, чтобы лучше понять случайность:

Вернемся к настоящему вопросу. В этом термине нет более или менее случайного:

оба только кажутся случайными!

В обоих случаях - просто rand() или rand() * rand() - ситуация одна и та же: через несколько миллиардов чисел последовательность повторится (!). Это кажется случайным для наблюдателя, потому что он не знает всей последовательности, но компьютер не имеет истинного случайного источника - поэтому он также не может производить случайность.

Например: погода случайная? У нас недостаточно сенсоров или знаний, чтобы определить, случайная погода или нет.

Ответ будет таким, это зависит, надеюсь, что rand () * rand () будет более случайным, чем rand (), но так:

  • оба ответа зависят от размера вашей стоимости в битах
  • что в большинстве случаев вы генерируете в зависимости от псевдослучайного алгоритма (который в основном является генератором чисел, который зависит от часов вашего компьютера, а не так много случайных).
  • сделайте ваш код более читабельным (и не вызывайте случайного бога случайного вуду с помощью этого вида мантры).

Хорошо, если вы проверите что-либо из вышеперечисленного, я предлагаю вам перейти к простой "rand ()". Потому что ваш код будет более читабельным (не спрашивайте себя, почему вы это написали, на... хорошо... более 2 секунд), его легко поддерживать (если вы хотите заменить функцию rand на super_rand).

Если вы хотите получить лучшую случайную выборку, я бы порекомендовал вам передавать ее из любого источника, который обеспечивает достаточное количество шума (радиостатический), а затем просто rand() должно быть достаточно.

Другие вопросы по тегам