Дозвольте мені заздалегідь вибачитися, тому що це трохи важко зрозуміти ...
Перш за все, ви вже знаєте, що java.util.Randomце зовсім не випадково. Це генерує послідовності ідеально передбачуваним способом із насіння. Ви абсолютно вірні, що оскільки насіння має лише 64 біти, воно може генерувати лише 2 ^ 64 різних послідовності. Якби ви якось генерували 64 справжні випадкові біти і використовували їх для вибору насіння, ви не могли б використовувати це насіння для випадкового вибору між усіма 52! можливі послідовності з однаковою ймовірністю.
Однак цей факт не має жодного наслідку , доки ви насправді не збираєтесь генерувати більше 2–64 послідовностей, доки немає нічого «особливого» чи «помітно особливого» щодо 2 ^ 64 послідовностей, які він може генерувати. .
Скажімо, у вас був набагато кращий PRNG, який використовував 1000-бітове насіння. Уявіть, що у вас було два способи ініціалізації - один із способів ініціалізував би його за допомогою всього насіння, а один із способів перемістив насіння до 64 біт перед ініціалізацією.
Якщо ви не знали, який це ініціалізатор, чи можете ви написати будь-який тест, щоб їх розрізнити? Якщо вам (не) пощастило закінчити ініціалізацію поганого з тими ж 64 бітами двічі, то відповідь - ні. Ви не могли розрізнити два ініціалізатори без детального знання про деякі слабкі сторони в конкретній реалізації PRNG.
Крім того, уявіть, що Randomклас мав масив з 2 ^ 64 послідовностей, які були відібрані повністю і випадковими в певний час у далекому минулому, і що насіння було лише індексом цього масиву.
Тож факт, що Randomвикористовує лише 64 біти для свого насіння, насправді не обов'язково є статистично проблемою, доки немає значних шансів, що ви будете використовувати одне і те ж насіння двічі.
Звичайно, для криптографічних цілей 64-бітового насіння просто недостатньо, тому що отримати систему для використання одного і того ж насіння двічі обчислювально.
Редагувати:
Я хочу додати, що, хоча все вищезазначене є правильним, реальна реалізація java.util.Randomне є приголомшливою. Якщо ви пишете карткову гру, можливо, використовуйте MessageDigestAPI, щоб генерувати хеш SHA-256 "MyGameName"+System.currentTimeMillis(), і використовуйте ці біти для переміщення колоди. Наведеним вище аргументом, якщо ваші користувачі не дуже грають в азартні ігри, вам не доведеться турбуватися, що currentTimeMillisповертається надовго. Якщо ваші користувачі справді грають в азартні ігри, використовуйте SecureRandomбез насіння.
Randomніколи не є реальними випадковими числами. Це PRNG, де P означає "псевдо". Для справжніх випадкових чисел вам потрібне джерело випадковості (наприклад, random.org).