Vorrei scusarmi in anticipo, perché è un po 'difficile da capire ...
Prima di tutto, sai già che java.util.Random
non è del tutto casuale. Genera sequenze in modo perfettamente prevedibile dal seme. Hai perfettamente ragione, dal momento che il seme è lungo solo 64 bit, può generare solo 2 ^ 64 sequenze diverse. Se dovessi in qualche modo generare 64 bit casuali reali e usarli per selezionare un seme, non potresti usare quel seme per scegliere casualmente tra tutti i 52! possibili sequenze con uguale probabilità.
Tuttavia, questo fatto non ha alcuna conseguenza finché non si generano più di 2 ^ 64 sequenze, purché non vi sia nulla di "speciale" o "notevolmente speciale" sulle sequenze 2 ^ 64 che può generare .
Diciamo che hai avuto un PRNG molto migliore che utilizzava semi a 1000 bit. Immagina di avere due modi per inizializzarlo: un modo lo inizializzerebbe usando l'intero seme e un modo lo avrebbe ridotto a 64 bit prima di inizializzarlo.
Se non sapessi quale inizializzatore fosse quale, potresti scrivere qualsiasi tipo di test per distinguerli? A meno che tu non sia stato (non) abbastanza fortunato da finire per inizializzare il cattivo con gli stessi 64 bit due volte, allora la risposta è no. Non è possibile distinguere tra i due inizializzatori senza una conoscenza dettagliata di alcuni punti deboli nell'implementazione specifica del PRNG.
In alternativa, immagina che la Random
classe avesse un array di 2 ^ 64 sequenze che sono state selezionate completamente e casualmente in qualche momento in un lontano passato e che il seme era solo un indice in questo array.
Quindi il fatto che Random
usi solo 64 bit per il suo seme è in realtà non è necessariamente un problema statistico, fintanto che non v'è alcuna possibilità significativa che verrà utilizzato lo stesso seme per due volte.
Naturalmente, per scopi crittografici , un seme a 64 bit non è abbastanza, perché ottenere un sistema per usare lo stesso seme due volte è fattibile dal punto di vista computazionale.
MODIFICARE:
Dovrei aggiungere che, anche se tutto quanto sopra è corretto, che l'implementazione effettiva di java.util.Random
non è eccezionale. Se stai scrivendo un gioco di carte, potresti usare l' MessageDigest
API per generare l'hash SHA-256 "MyGameName"+System.currentTimeMillis()
e usare quei bit per mescolare il mazzo. Con l'argomento sopra, fintanto che i tuoi utenti non stanno davvero giocando d'azzardo, non devi preoccuparti che currentTimeMillis
ritorni a lungo. Se i tuoi utenti stanno davvero giocando d'azzardo, usa SecureRandom
senza seed.
Random
non sono mai numeri casuali reali . È un PRNG, dove P sta per "pseudo". Per numeri casuali reali , hai bisogno di una fonte di casualità (come random.org).