Est Collections.shuffle() vraiment suffisamment aléatoire? Des exemples pratiques semblent rejeter cette déclaration
J'ai 1000 objets uniques dans un java.util.List
, chacun se référant à une image, chaque image dans le 1000-liste est unique et maintenant, je tiens à les mélanger, de sorte que je peux utiliser les 20 premiers objets et de les présenter sur le site web de l'utilisateur.
L'utilisateur peut alors cliquer sur un bouton disant "Shuffle", et j'ai récupérer les 1000 images de nouveau à partir de zéro et d'appeler de nouveau shuffle()
.
Cependant, il semble que de 1000 objets de l'image, j'ai très souvent de voir la même image, encore et encore, entre le 20-image-sélections.
Quelque chose semble incorrect, une meilleure suggestion, des conseils?
Mon code est très simple:
List<String> imagePaths = get1000Images();
Collections.shuffle(imagePaths);
int i = 0;
for (String path: imagePaths) {
... do something with the path ...
i++;
if (i >= 20) break;
}
Je sais que Collections.shuffle()
est bien distribué:
voir, par exemple, http://blog.ryanrampersad.com/2012/03/03/more-on-shuffling-an-array-correctly/
Cependant, j'ai juste le sentiment que la probabilité de voir la même image, encore et encore dans une série de 20 images de 1000 devrait être beaucoup moins...
Entrées très apprécié.
Mon suppose que, c'est que vous avez réellement obtenu le même chemin de l'image plusieurs fois, ou plusieurs chemins d'image que en fait, ont la même image. Au-delà, il est difficile de dire avec ce peu d'informations...
Jetez un oeil à ma réponse ici, pourrait être utile. Peut-être que vous devriez brancher différents
Random
mise en œuvre?pertinent de dilbert
En fait, vous devriez pas créer une nouvelle instance de
Random
par shuffle
, sauf si vous avez une forte source de hasard seed
. Sinon, réutiliser le même. Peut-être SecureRandom
avec des semences de bonne?OriginalL'auteur basZero | 2012-03-14
Vous devez vous connecter pour publier un commentaire.
Si vous êtes montrant 20 images sur 1000, la probabilité de voir un de que 20 répété dans la prochaine itération est d'environ 0.34 sorte que vous ne devriez pas être surpris de voir des images de la répétition.
Les chances de voir une image spécifique est toujours l'un sur mille, mais si vous êtes à la recherche pour une vingtaine d'images, les chances sont beaucoup plus élevés.
Nous pouvons calculer la probabilité d'aucune de ces 20 images de répéter que:
Et donc la probabilité de voir une répétition est un moins, ou environ de 0,34.
Et la probabilité de voir une image répétée dans les deux prochaines itérations est:
En d'autres termes, il est plus que probable que vous verrez une image répétée au cours des deux cycles suivants. (Et ce n'est pas y compris les images répétées à partir du deuxième cycle dans le troisième qui ne fera que rendre plus probable.)
Pour ce que ça vaut, voici une partie du code Java pour faire le calcul ci-dessus:
1 - 0.66 = 0.34
Fixe.
Ou peut-être il est censé être
1 - 0.67 = 0.33
?Le code ci-dessus renvoie
0.6649897
qui je suis arrondissement de0.66
. Je ne suis pas sûr que les valeurs exactes trop d'importance, le point est que vous pouvez vous attendre à voir l'un des 20 dernières images de répétition d'environ un tous les trois fois.OriginalL'auteur Dave Webb
Sa nature humaine à voir des modèles qui ne sont pas là. Beaucoup de gens voir des formes dans les planètes et les étoiles que de guider leur vie.
Dans les 1000 premiers chiffres de PI, il y a six neufs dans une rangée. Est-ce à dire que les chiffres de PI ne sont pas aléatoires? pas de. Le schéma ne se reproduise pas, pas plus que votre pourrait s'attendre.
Cela dit, le Hasard n'est pas complètement aléatoire et il va répéter après 2^48 appels. (il utilise un 48 bits de la graine), Cela signifie qu'il pas possible de produire tous les possibles
long
oudouble
de l'utiliser. Si vous voulez plus de hasard vous pouvez utiliser SecureRandom avec shuffle à la place.Cela ressemble à ce que vous voulez, c'est quelque chose comme cela
Cela permettra d'assurer que vous ne voyez pas la même image dans les 500 derniers appels.
+1 pour les planètes, les étoiles et 2^48. 🙂
Pour utiliser le SecureRandom, vous pouvez le faire:
Collections.shuffle(imagePaths, new SecureRandom());
OriginalL'auteur Peter Lawrey
Votre intuition est correcte pour une image spécifique [vous ne sont pas susceptibles de voir un image spécifique plus et plus de nouveau], mais pas pour une image générale [vous êtes susceptible de voir de l'image répéter]. C'est l'un de ces endroits de la probabilité que nos automatique intuition est fausse...
Cela me rappelle le paradoxe d'anniversaire, ce qui contredit l'intuition, et dit: - pour un groupe de 23 personnes, la probabilité de 2 d'entre eux ayant la même date d'anniversaire est de 0,5, beaucoup plus que l'intuition attend!
OriginalL'auteur amit
J'ai fait un 52 cartes shuffle quatre fois et a marqué à chaque fois à chaque itération répété exactement la même carte dans le même logement, ce qui m'a donné environ 14 208 cartes, qui était d'environ 93,3% de hasard.
OriginalL'auteur Nicholas
À la suite de votre question, j'ai écrit le programme suivant. J'ai créé la liste d'entiers séquentiels et la traînait 10, 100, 1000 et 10000 fois. Après chaque série de remaniements j'ai vérifié la valeur de l'élément en 5ème position de la matrice et créé tableau de compteurs: combien de fois chaque numéro s'affiche en 5ème position.
Voici le programme:
Et voici les résultats:
10: [0, 1, 1, 1, 2, 0, 0, 3, 2, 0]
100: [11, 9, 9, 7, 10, 12, 13, 13, 8, 8]
1000: [100, 101, 107, 101, 95, 96, 109, 83, 93, 115]
10000: [1015, 942, 990, 1003, 1015, 1037, 977, 1060, 950, 1011]
Comme vous pouvez le voir le "randomality" dépend du nombre de remaniements. Si vous shuffle tableau 10 fois le minimum compteur est 0 et le maximum est de 3.
La différence entre ces valeurs pour 100 brasse (en cents) beaucoup plus petite.
Les nombres a presque la même pour 10000 mélange.
Je pense que ce test de modèles à votre cas d'utilisation: vous montrant des images en position spécifique de déplacés de la collection.
Veuillez voir le post de @amit qui décrit le sens de lecture aléatoire.
Donc, la solution pour vous est de mélanger votre tableau 10 fois.
EDIT: @Dave Webb a donné la parfaite explication pour le cas.
La deuxième réflexion est la suivante: vous avez réellement n'avez pas à shuffle vous liste de plus de 1000 éléments à prendre 20 premier élément. Il suffit de prendre 20 éléments aléatoires. Vous obtiendrez le même effet, mais beaucoup plus efficace solution:
mon exemple de code prend en considération en prenant même des éléments à deux reprises: j'ai utilisé le Set pour enregistrer les résultats et itéré jusqu'à ce que la taille de l'ensemble est de 20.
Vrai, désolé, pensé que vous auriez utilisé
List
Et il y a une très simple (et beaucoup plus efficace) solution pour éviter ce problème; voir ici. Yep c'est vrai, si nous devions le faire correctement, que nous venions de ré-écrire l'algorithme de shuffle déjà en cours d'utilisation. Pour prouver le caractère aléatoire vous jamais croyez-le à votre intuition - que vais en principe toujours être mal. Il existe des tests statistiques (khi Carré, de Kolmogorov-Smirnov,..). Aussi ne jamais faire
nextInt() % size
si vous voulez une distribution uniforme, qui, évidemment, ne fonctionnent que dans de rares cas.Appel shuffle à plusieurs reprises n'a pas de sens à partir d'une statistique pov (si vous pensez le contraire, je suis toujours partante pour certains tests de chi carré, note que "n'a pas l'air aléatoire" est sans intérêt). Mais la question est: Quel est l'algorithme de shuffle n'est en fait prendre aléatoire des éléments de la liste. D'où la modification de la solution est en fait un pas vraiment efficace shuffle algorithme avec quelques bugs.
OriginalL'auteur AlexR
Avec ce code, si vous voyez la même image, cela signifie la même image existe de nombreuses reprises dans la liste. Où vous êtes l'obtention de votre 1000 images à partir, il y a des doublons.
Si votre code est vraiment la façon dont vous l'avez, là où vous êtes juste de parcourir la liste et pas de modification de la liste après la première shuffle, le seul moyen, vous pouvez obtenir des doublons dans votre choix de 20 images est si il y a des doublons dans la liste pour commencer.
Collections.shuffle()
ne pas insérer des copies, il vient de se réorganise les éléments existants.Il est de voir la même image parmi la sélection des 20 plus et plus d'une sur plusieurs remaniements.
Ah, OK. Ce n'était pas clair à partir de la formulation de la question.
Désolé pour la mauvaise formulation, corrigé maintenant, j'espère que c'est plus clair...
OriginalL'auteur Graham Borland