Следующее утверждение print выдает «hello world». Кто-нибудь может объяснить это?
System.out.println(randomString(-229985452) + " " + randomString(-147909649));
И randomString()
выглядит так:
public static String randomString(int i)
{
Random ran = new Random(i);
StringBuilder sb = new StringBuilder();
while (true)
{
int k = ran.nextInt(27);
if (k == 0)
break;
sb.append((char)('`' + k));
}
return sb.toString();
}
n
вfor (int n = 0; ; n++)
. Они могли бы использоватьfor(;;)
илиwhile(true)
вместо этого!Ответы:
Когда экземпляр
java.util.Random
конструируется с определенным параметром начального числа (в данном случае-229985452
или-147909649
), он следует алгоритму генерации случайного числа, начинающемуся с этого начального значения.Каждый
Random
построенный с одним и тем же семенем будет каждый раз генерировать один и тот же набор чисел.источник
"hello\0"
и есть 6 элементов"world\0"
. Если вы предполагаете, что генератор действительно случайный, то шансы получить искомую последовательность будут равны 1 к 27 ^ 6 (387 420 489), так что это довольно впечатляюще, но не настолько ошеломительно!"Hello"
"World"
), или использовать122-k
вместо96+k
, или ...Другие ответы объясняют почему, но вот как.
Учитывая экземпляр
Random
:Первые 6
r.nextInt(27)
генерируемых чисел :и первые 6 чисел, которые
r.nextInt(27)
генерируют данныеRandom r = new Random(-147909649)
:Затем просто добавьте эти числа к целочисленному представлению символа
`
(которое равно 96):источник
new Random(-229985452).nextInt(27)
всегда возвращает 8.new Random()
не возвращает число вообще.Random
не криптографически безопасен (я уверен, что это Twister Mersenne, но не цитируйте меня по этому поводу), возможно, можно вернуться назад от «Я хочу эти цифры» к «это семя я бы использовал ". Я сделал нечто подобное со стандартным C линейным конгруэнтным генератором.Я просто оставлю это здесь. Тот, у кого есть много свободного времени (CPU), не стесняйтесь экспериментировать :) Кроме того, если вы освоили какое-то fork-join-fu, чтобы заставить эту вещь сжигать все ядра процессора (просто потоки скучны, верно?), Пожалуйста, поделитесь ваш код. Я буду очень признателен.
Вывод:
источник
nextInt(27)
означает в пределах диапазона[0, 26]
.Все здесь проделали огромную работу, объяснив, как работает код, и продемонстрировали, как вы можете создать свои собственные примеры, но вот информационный теоретический ответ, показывающий, почему мы можем разумно ожидать, что существует решение, которое в конечном итоге найдет поиск методом перебора.
26 различных строчных букв образуют наш алфавит
Σ
. Чтобы позволить генерировать слова различной длины, мы дополнительно добавляем символ-терминатор,⊥
чтобы получить расширенный алфавитΣ' := Σ ∪ {⊥}
.Позвольте
α
быть символом и X равномерно распределенной случайной величиной надΣ'
. Вероятность получения этого символаP(X = α)
и его информационное содержаниеI(α)
определяются следующим образом:Для слова
ω ∈ Σ*
и его⊥-
прекращенного аналогаω' := ω · ⊥ ∈ (Σ')*
мы имеемПоскольку генератор псевдослучайных чисел (PRNG) инициализируется с помощью 32-разрядного начального числа, мы можем ожидать, что большинство слов длиной до
быть сгенерированным хотя бы одним семенем. Даже если бы нам пришлось искать слово из 6 символов, мы все равно добились бы успеха в 41,06% случаев. Не слишком потрепанный.
Для 7 писем мы смотрим ближе к 1,52%, но я не понял этого, прежде чем попробовать:
Смотрите вывод: http://ideone.com/JRGb3l
источник
I(⍵)
переставленное уравнение.I(⍵)
32 (биты) и|⍵|
получается 5 (символы).Я написал быструю программу, чтобы найти эти семена:
Сейчас он работает в фоновом режиме, но уже найдено достаточно слов для классической панграммы:
( Демонстрация на ideone. )
Ps.
-727295876, -128911, -1611659, -235516779
,источник
Я был заинтригован этим, я запустил этот генератор случайных слов в списке словарных слов. Диапазон: от Integer.MIN_VALUE до Integer.MAX_VALUE
Я получил 15131 хитов.
Печать
источник
Фактически большинство генераторов случайных чисел являются «псевдослучайными». Это линейные конгруэнтные генераторы или LCG ( http://en.wikipedia.org/wiki/Linear_congruential_generator )
LCG вполне предсказуемы, учитывая фиксированное начальное число. В основном, используйте начальное число, которое дает вам ваше первое письмо, затем напишите приложение, которое продолжает генерировать следующее целое число (символ), пока вы не нажмете следующую букву в вашей целевой строке и не запишите, сколько раз вам приходилось вызывать LCG. Продолжайте, пока вы не сгенерируете каждую букву.
источник
/dev/urandom
устройство для чтения случайных данных. Однако это скудный ресурс. Таким образом, такие случайные данные обычно используются для заполнения PRNG.urandom
что все еще псевдослучайный en.wikipedia.org/wiki//dev/random/dev/random
. В статье, которую я цитировал выше, говорится, что ядро Linux генерирует энтропию из таймингов клавиатуры, движений мыши и IDE и делает случайные символьные данные доступными для других процессов операционной системы через специальные файлы / dev / random и / dev / urandom. Это позволило мне поверить, что это действительно случайно. Может быть, это не совсем правильно. Но,/dev/random
по крайней мере, содержит некоторую энтропию.Поскольку многопоточность очень проста с Java, вот вариант, который ищет начальное число, используя все доступные ядра: http://ideone.com/ROhmTA
источник
L
и изменить тип аргумента наlong
, т.е.randomString(long i)
чтобы поиграться. :)Случайные всегда возвращают одну и ту же последовательность. Он используется для перетасовки массивов и других операций в качестве перестановок.
Чтобы получить разные последовательности, необходимо инициализировать последовательность в некотором положении, называемом «семя».
RandomSting получает случайное число в позиции i (seed = -229985452) «случайной» последовательности. Затем использует код ASCII для следующих 27 символов в последовательности после начального положения, пока это значение не станет равным 0. Это возвращает «привет». Та же операция сделана для «мира».
Я думаю, что код не работает ни для каких других слов. Парень, который запрограммировал это, знает случайную последовательность очень хорошо.
Это очень хороший компьютерный код!
источник
Основным является случайный класс, построенный с одним и тем же начальным числом, который будет каждый раз генерировать один и тот же шаблон чисел.
источник
Полученный из ответа Дениса Тульского , этот метод создает семя.
источник
В документации по Java это преднамеренная функция при указании начального значения для класса Random.
http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Random.html
Как ни странно, вы могли бы подумать, что существуют неявные проблемы безопасности, связанные с предсказуемыми «случайными» числами.
источник
Random
«устанавливает начальное значение генератора случайных чисел на значение, которое, скорее всего, будет отличаться от любого другого вызова этого конструктора» ( javadoc ). В текущей реализации это комбинация текущего времени и счетчика.Речь идет о «семени». Те же семена дают тот же результат.
источник
Вот небольшое улучшение для ответа Дениса Тульского . Это сокращает время вдвое
источник
Вывод
источник