[JAVA] La fin de la programmation catastrophique # 02 "Il est difficile d'obtenir 5 et 6 de dés ... J'en ai envie, alors considérez les nombres aléatoires"

La fin de la programmation catastrophique # 02 "Il est difficile d'obtenir 5 et 6 de dés ... J'en ai envie, alors considérez les nombres aléatoires"

Un programmeur ordinaire le comprend intuitivement et par réflexe, Je voudrais écrire un article sur une histoire rudimentaire et simple. C'est rudimentaire, mais je suis un gros programmeur, donc je le fais souvent. J'écrirai une petite histoire comme un commandement pour moi-même.

S'il y a des erreurs ou du contenu inapproprié, veuillez commenter Nous examinerons les corrections et ajustements du contenu.

1. Aléatoire

Comme Random.nextInt (), Je pense que de nombreux programmeurs ont utilisé la méthode pour obtenir la valeur aléatoire.

Une fonction ou une méthode qui obtient un nombre aléatoire de valeurs entières supérieur ou égal à 0 et inférieur à 9 est, par exemple, Pour Java, Random.nextInt (10), Pour C #, Random.Next (10), Pour Python, ce serait random.randint (0, 9)`.

Pour de nombreux programmeurs, la façon dont les nombres aléatoires sont dispersés et leur périodicité est Parfois, plus vous vous sentez frustrant, plus les valeurs sont biaisées.

La plupart du temps, nous traitons généralement des nombres pseudo-aléatoires, Des valeurs aléatoires sont générées par l'algorithme. Il existe différentes bizarreries en fonction de l'algorithme utilisé (utilisé en interne), Cette fois, je laisse ce point pour le moment.

(** Sinon pour le chiffrement, ** En raison de sa variation et de la durée de la périodicité, ma recommandation personnelle est Un nombre aléatoire généré par Mercenne Twister. )

L'article suivant est un exemple de Java, mais je pense que c'est ** la même chose pour les autres langages **. La partie de rand.nextInt (10) Si vous le lisez comme rand.Next (10) pour C #, random.randint (0, 9) pour Python, etc., vous pouvez probablement l'imaginer.

2. Pour le moment, j'ai essayé d'obtenir des valeurs aléatoires 10 milliards de fois avec Java

Pour le moment, obtenons une valeur aléatoire 10 milliards de fois avec Java. Utilisez Random.nextInt (10) pour obtenir les valeurs aléatoires de 0 à 9 10 milliards de fois, Le nombre d'apparitions de chacun a été compté.

Random rand = new Random();

long[] numCounter = new long[10];

for(long count = 0; count < 10000000000L; count++) {
  int value = rand.nextInt(10);
  numCounter[value]++;
}

** Le résultat est le suivant. ** **

valeur de valeur Nombre d'apparitions
0 1,000,017,191
1 999,943,364
2 999,983,662
3 1,000,012,905
4 1,000,049,567
5 1,000,001,706
6 999,982,619
7 1,000,068,926
8 999,966,928
9 999,973,132

Concernant la variation, il peut être préférable de l'analyser mathématiquement, Cette fois, ce n'est pas une session de mathématiques, alors prenons une décision rapide. En se concentrant uniquement sur les ** occurrences ** simples de chaque nombre pour 10 milliards d'essais, Il ne semble pas y avoir de gros problème.

Dans l'implémentation standard de Java, les nombres aléatoires sont générés par la méthode de congruence linéaire, En ce qui concerne ces caractéristiques, je vais les mettre sur l'étagère cette fois.

3. Un ajustement soigneux des valeurs générées peut avoir des conséquences désastreuses.

ʻInt value = rand.nextInt (10); pour value of Calculons pour que le résultat soit le résultat de 6 dés. La raison pour laquelle vous devriez le définir surrand.nextInt (6)` est ** cette fois, aucun ** n'a lié le jeu.

ʻInt sainome = (valeur% 6) + 1; Il semble que vous puissiez lancer 1 à 6 des dés. Dans la partie de(valeur% 6), il passe de 0 à 5`, donc après cela, ajoutez simplement un selon les dés.

Si vous ne dormez pas suffisamment après le match qui a duré toute la nuit, il semble que tout ira bien, mais Ce calcul n'est pas du tout juste.

valeur du sainome Nombre d'apparitions
1 1,999,999,810
2 2,000,012,290
3 1,999,979,833
4 1,999,986,037
5 1,000,049,567
6 1,000,001,706

Les 1er au 4ème yeux sont apparus environ 2 milliards de fois, Les 5ème et 6ème yeux ne sont apparus qu'environ 1 milliard de fois, Il y a à peu près une double différence.

4. Pourquoi les 5 et 6 de Sagami ne sont-ils pas apparus autant ...

Cette fois, je l'ai essayé avec un petit nombre, donc je pense que c'était facile à remarquer. Vous pouvez facilement le découvrir en organisant côte à côte la valeur valeur et la (valeur% 6) valeur.

valeur de valeur (value % 6)La valeur du
0 0
1 1
2 2
3 3
4 4
5 5
6 0
7 1
8 2
9 3

Dans le tableau ci-dessus, il y a deux «0, 1, 2, 3» comme «(value% 6) value», Il n'y a qu'un seul «4, 5». Ce n'est pas juste.

5. Fin

Les valeurs aléatoires varient parfois de manière frustrante, Cela peut être encore plus désastreux, selon la façon dont vous ajoutez vos soins (si vous voulez calculer des nombres plus aléatoires).

Cet exemple met l'accent sur la facilité d'imagination et est un exemple assez extrême, donc En fait, il peut y avoir quelques cas où vous êtes accro à quelque chose de similaire à cette fois, Je pense que c'est une bonne idée de toujours être vigilant lors de l'utilisation de nombres aléatoires.

6. Contre-mesures

Dans cet exemple, ʻInt value = rand.nextInt (6); ʻest bien, mais Pensons au ** jeu lié ** que rand.nextInt (6) ne peut pas être fait.

La limite de l'équité sera probablement de savoir si la «valeur de valeur» est «5 ou moins». À part cela, il semble tout à fait le cas en jugeant qu'il est injuste et en ignorant la valeur injuste.

Prenons également le cas de ʻint value = rand.nextInt (1000); `. La «valeur» est un nombre aléatoire de «0 à 999». Dans ce cas, jugez si la "valeur de valeur" est "5 ou moins", Si vous ignorez «5 ou moins comme injuste», un nombre considérable sera ignoré, Ce sera un algorithme assez inefficace.

Ce qui doit être ignoré est probablement proche de «999».

valeur de valeur (value % 6)La valeur du
... ...
990 0
991 1
992 2
993 3
994 4
995 5
996 0
997 1
998 2
999 3

Dans ce cas, jusqu'à «995 est juste» et de «996 est injuste».

Cela ressemble à ceci lorsqu'il est incorporé dans l'algorithme.

  1. ʻint group = (1000/6); `pour savoir combien il y a de groupes équitables.
  2. Utilisez ʻint unfairValueMin = (group * 6); `pour trouver la valeur minimale injuste.
  3. Vérifiez la valeur générée par ʻint value = rand.nextInt (1000); Sivalue <unfairValueMin est true`, elle est jugée juste et adoptée. Autre que cela, comme injuste Générez à nouveau une valeur aléatoire et répétez la vérification pour voir si elle est juste.
  4. Trouvez (valeur% 6) en utilisant la valeur jugée juste.

Eh bien, il existe de nombreux cas où il n'est pas nécessaire de trouver une juste valeur excessive, En utilisant un exemple comme celui-ci, Au contraire, il existe également une méthode pour générer facilement une valeur de nombre aléatoire biaisée par votre propre volonté.

Par exemple, dans l'exemple d'émission de «0 à 5»,

for(int i = 0; i < 100; i++) {
  int value = (rand.nextInt(6) + rand.nextInt(6)) / 2;

  System.out.println(value);
}

Et,

for(int i = 0; i < 100; i++) {
  int value = rand.nextInt(3) + rand.nextInt(4);

  System.out.println(value);
}

Et,

for(int i = 0; i < 100; i++) {
  int value = (rand.nextInt(6) + rand.nextInt(6) + rand.nextInt(6)) / 3;

  System.out.println(value);
}

Il peut être amusant de le déplacer ou de penser à ce qui se passe. (Dans le dernier code, «5» apparaît rarement, mais «2» et «3» devraient apparaître en désordre.)

Le degré de préjugé dépend de la façon dont vous le faites. En pratique, vous aurez peut-être besoin d'une méthode plus rigoureuse.

Recommended Posts

La fin de la programmation catastrophique # 02 "Il est difficile d'obtenir 5 et 6 de dés ... J'en ai envie, alors considérez les nombres aléatoires"
The End of Catastrophic Programming # 04 "Mistaken Exception Catch Range"
J'ai vérifié les versions de Blender et Python
Je veux connaître la nature de Python et pip
[Introduction à Python] J'ai comparé les conventions de nommage de C # et Python.
J'ai résumé comment changer les paramètres de démarrage de GRUB et GRUB2
J'ai étudié le comportement de la différence entre lien dur et lien symbolique
J'ai essayé de comprendre la normalisation spectrale et la décomposition de valeurs singulières qui contribuent à la stabilité du GAN.