Oui et non, selon ce que vous entendez par «la seule façon». Oui, dans la mesure où il n'y a pas de méthode garantie pour se terminer, le mieux que vous puissiez faire (pour les valeurs génériques de et ) est un algorithme qui se termine avec la probabilité 1. Non, en ce que vous pouvez réduire le «gaspillage» aussi petit comme vous voulez.RNR
Pourquoi la résiliation garantie est impossible en général
Supposons que vous ayez un moteur de calcul déterministe (une machine de Turing ou tout ce qui fait flotter votre bateau), plus un oracle qui génère des éléments aléatoires de l' ensemble d' éléments . Votre objectif est de générer un élément de l' ensemble d'éléments . La sortie de votre moteur ne dépend que de la séquence de valeurs renvoyées par l'oracle; c'est une fonction de cette séquence potentiellement infinie .[ 0 .. R - 1 ] N [ 0 , N - 1 ] f ( r 0 , r 1 , r 2 , … )R[0..R−1]N[0,N−1]f(r0,r1,r2,…)
Supposons que votre moteur appelle l'oracle au maximum fois. Il peut y avoir des traces pour lesquelles l'oracle est appelé moins de fois; si c'est le cas, appeler l'oracle extra times pour qu'il soit toujours appelé exactement fois ne change pas la sortie. Donc, sans perte de généralité, nous supposons que l'oracle est appelé exactement fois. Alors la probabilité du résultat est le nombre de séquences telles que . Puisque l'oracle est un générateur aléatoire uniforme, chaque séquence est équiprobable et a la probabilité . La probabilité de chaque résultat est donc de la formem m m x ( r 0 , … , r mmmmmxf( r 0 ,…, r m - 1 )=x1 / R m A / R m A0 R m(r0,…,rm−1)f(r0,…,rm−1)=x1/RmA/Rmoù est un entier compris entre et .A0Rm
Si divise pour quelques , alors vous pouvez générer une distribution uniforme sur éléments en appelant le générateur aléatoire fois (cela est laissé au lecteur comme exercice). Dans le cas contraire, cela est impossible: il n'y a aucun moyen d'obtenir un résultat avec une probabilité . Notez que la condition équivaut à dire que tous les facteurs premiers de sont également des facteurs de (c'est plus permissif que ce que vous avez écrit dans votre question; par exemple, vous pouvez choisir un élément aléatoire parmi 4 avec une foire à 6 faces mourir, même si 4 ne divise pas 6).R m m N m 1 / N N RNRmmNm1/NNR
Réduire les déchets
Dans votre stratégie, lorsque , vous n'avez pas à redessiner immédiatement. Intuitivement, il reste un peu d'entropie dans que vous pouvez conserver dans le mix.[ kr≥kN[kN..R−1]
Supposons un instant que vous continuerez en fait à générer des nombres aléatoires en dessous de pour toujours, et que vous en générerez à la fois en faisant tirages. Si vous effectuez un échantillonnage de rejet simple sur cette génération groupée, le gaspillage sur attire est , c'est-à-dire le reste divisé par le nombre de tirages. Cela peut être aussi petit que . Lorsque et sont des coprimes, vous pouvez rendre les déchets arbitrairement petits en choisissant des valeurs suffisamment grandes de . Pour les valeurs générales de etu d d R d - kNuddRd−kNudRdmodNuR N d R N pgcd ( R , N ) N / pgcd ( R , N )gcd(R,N)RNdRN, le calcul est plus compliqué car vous devez prendre en compte la génération de et séparément, mais là encore, vous pouvez rendre les déchets arbitrairement petits avec des groupes suffisamment grands.gcd(R,N)N/gcd(R,N)
En pratique, même avec des nombres aléatoires relativement inefficaces (par exemple en cryptographie), il vaut rarement la peine de faire autre chose qu'un simple échantillonnage de rejet, sauf si est petit. Par exemple, en cryptographie, où est généralement une puissance de 2 et est généralement des centaines ou des milliers de bits, la génération uniforme de nombres aléatoires se déroule généralement par échantillonnage par rejet direct dans la plage souhaitée.R NNRN