La déclaration d'impression suivante imprimerait "bonjour le monde". Quelqu'un pourrait-il expliquer cela?
System.out.println(randomString(-229985452) + " " + randomString(-147909649));
Et randomString()
ressemble à ceci:
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
infor (int n = 0; ; n++)
. Ils pourraient utiliserfor(;;)
ou à lawhile(true)
place!Réponses:
Lorsqu'une instance de
java.util.Random
est construite avec un paramètre de départ spécifique (dans ce cas-229985452
ou-147909649
), elle suit l'algorithme de génération de nombres aléatoires commençant par cette valeur de départ.Chaque
Random
construit avec la même graine générera à chaque fois le même schéma de nombres.la source
"hello\0"
et"world\0"
. Si vous supposiez un générateur vraiment aléatoire, les chances seraient de 1 sur 27 ^ 6 (387 420 489) d'obtenir la séquence que vous cherchiez - c'est donc assez impressionnant mais pas tout à fait époustouflant!"Hello"
"World"
), ou utiliser à la122-k
place de96+k
, ou ...Les autres réponses expliquent pourquoi, mais voici comment.
Étant donné une instance de
Random
:Les 6 premiers nombres
r.nextInt(27)
générés sont:et les 6 premiers nombres qui
r.nextInt(27)
génèrent donnésRandom r = new Random(-147909649)
sont:Ajoutez ensuite ces nombres à la représentation entière du caractère
`
(qui est 96):la source
new Random(-229985452).nextInt(27)
renvoie toujours 8.new Random()
ne renvoie aucun numéro du tout.Random
n'est pas sécurisée sur le plan cryptographique (je suis presque sûr qu'il s'agit d'un Twister de Mersenne, mais ne me citez pas à ce sujet), il est probablement possible de revenir en arrière de "Je veux ces chiffres" à "c'est la graines que j'utiliserais ". J'ai fait quelque chose de similaire avec le générateur congruentiel linéaire standard C.Je vais juste le laisser ici. Quiconque a beaucoup de temps (CPU) à perdre, n'hésitez pas à expérimenter :) De plus, si vous avez maîtrisé un fork-join-fu pour que cette chose brûle tous les cœurs du processeur (seuls les threads sont ennuyeux, non?), Veuillez partager votre code. Je l'apprécierais grandement.
Production:
la source
nextInt(27)
signifie dans la plage[0, 26]
.Tout le monde ici a fait un excellent travail pour expliquer comment le code fonctionne et montrer comment vous pouvez construire vos propres exemples, mais voici une réponse théorique d'information montrant pourquoi nous pouvons raisonnablement nous attendre à une solution que la recherche par force brute trouvera finalement.
Les 26 lettres minuscules différentes forment notre alphabet
Σ
. Pour permettre de générer des mots de différentes longueurs, nous ajoutons en outre un symbole de terminaison⊥
pour produire un alphabet étenduΣ' := Σ ∪ {⊥}
.Soit
α
un symbole et X une variable aléatoire uniformément répartieΣ'
. La probabilité d'obtenir ce symboleP(X = α)
et son contenu d'informationI(α)
sont données par:Pour un mot
ω ∈ Σ*
et son⊥-
homologue terminéω' := ω · ⊥ ∈ (Σ')*
, nous avonsÉtant donné que le générateur de nombres pseudo-aléatoires (PRNG) est initialisé avec une graine 32 bits, nous pouvons nous attendre à la plupart des mots de longueur allant jusqu'à
à générer par au moins une graine. Même si nous devions rechercher un mot à 6 caractères, nous réussirions quand même environ 41,06% du temps. Pas trop mal.
Pour 7 lettres, nous nous rapprochons de 1,52%, mais je ne l'avais pas réalisé avant de l'essayer:
Voir la sortie: http://ideone.com/JRGb3l
la source
I(⍵)
équation réarrangée.I(⍵)
est 32 (bits) et|⍵|
se révèle être 5 (symboles).J'ai écrit un programme rapide pour trouver ces graines:
Je l'ai maintenant en arrière-plan, mais il a déjà trouvé suffisamment de mots pour un pangram classique:
( Démo sur ideone. )
Ps.
-727295876, -128911, -1611659, -235516779
.la source
Cela m'a intrigué, j'ai exécuté ce générateur de mots aléatoires sur une liste de mots du dictionnaire. Plage: Integer.MIN_VALUE à Integer.MAX_VALUE
J'ai eu 15131 hits.
Impressions
la source
La plupart des générateurs de nombres aléatoires sont, en fait, «pseudo aléatoires». Ce sont des générateurs congruentiels linéaires, ou LCG ( http://en.wikipedia.org/wiki/Linear_congruential_generator )
Les LCG sont assez prévisibles étant donné une semence fixe. Fondamentalement, utilisez une graine qui vous donne votre première lettre, puis écrivez une application qui continue de générer le prochain int (char) jusqu'à ce que vous frappiez la lettre suivante dans votre chaîne cible et notez combien de fois vous avez dû appeler le LCG. Continuez jusqu'à ce que vous ayez généré chaque lettre.
la source
/dev/urandom
appareil pour lire des données aléatoires. Il s'agit cependant d'une ressource rare. Ainsi, ces données aléatoires sont normalement utilisées pour amorcer des PRNG.urandom
est toujours pseudo aléatoire en.wikipedia.org/wiki//dev/random/dev/random
. L'article que j'ai cité ci-dessus dit que le noyau Linux génère l'entropie à partir des synchronisations du clavier, des mouvements de la souris et des synchronisations IDE et met les données de caractères aléatoires à la disposition des autres processus du système d'exploitation via les fichiers spéciaux / dev / random et / dev / urandom. Cela me laisse croire que c'est vraiment aléatoire. Peut-être que ce n'est pas tout à fait correct. Mais contient/dev/random
au moins une certaine entropie.Le multi-threading étant très simple avec Java, voici une variante qui recherche une graine en utilisant tous les cœurs disponibles: http://ideone.com/ROhmTA
la source
L
et changer le type d'argument enlong
, c'est-randomString(long i)
à- dire afin de jouer. :)Random renvoie toujours la même séquence. Il est utilisé pour mélanger les tableaux et autres opérations comme permutations.
Pour obtenir différentes séquences, il est nécessaire d'initialiser la séquence dans une certaine position, appelée "graine".
RandomSting obtient le nombre aléatoire dans la position i (seed = -229985452) de la séquence "random". Utilise ensuite le code ASCII pour les 27 caractères suivants dans la séquence après la position de départ jusqu'à ce que cette valeur soit égale à 0. Cela renvoie le "bonjour". La même opération est effectuée pour "monde".
Je pense que le code n'a pas fonctionné pour d'autres mots. Le gars qui a programmé qui connaît très bien la séquence aléatoire.
C'est un très bon code geek!
la source
Le principe est que la classe aléatoire construite avec la même graine va générer le même modèle de nombres à chaque fois.
la source
Dérivée de la réponse de Denis Tulskiy , cette méthode génère la graine.
la source
Dans les documents Java, il s'agit d'une fonctionnalité intentionnelle lors de la spécification d'une valeur de départ pour la classe Random.
http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Random.html
Curieusement cependant, on pourrait penser qu'il y a des problèmes de sécurité implicites à avoir des nombres «aléatoires» prévisibles.
la source
Random
"définit la graine du générateur de nombres aléatoires à une valeur très susceptible d'être distincte de toute autre invocation de ce constructeur" ( javadoc ). Dans l'implémentation actuelle, il s'agit d'une combinaison de l'heure actuelle et d'un compteur.Il s'agit de "semence". Les mêmes graines donnent le même résultat.
la source
Voici une amélioration mineure pour la réponse de Denis Tulskiy . Cela réduit le temps de moitié
la source
Production
la source