Comment générer un hasard BigInteger valeur en Java?
J'ai besoin de générer arbitrairement grand entiers aléatoires compris entre 0 (inclus) au n (exclusif). Ma première pensée a été d'appeler nextDouble
et multiplier par n, mais une fois que n est plus grand que 253, les résultats ne seraient plus distribués de manière uniforme.
BigInteger
a la suite de constructeur disponibles:
public BigInteger(int numBits, Random rnd)
Constructions généré de façon aléatoire une BigInteger, distribués de manière uniforme sur l'intervalle de 0 à (2numBits - 1), inclus.
Comment cela peut-il être utilisé pour obtenir une valeur aléatoire dans la plage de 0 - n, où n n'est pas une puissance de 2?
Vous devez vous connecter pour publier un commentaire.
Utiliser une boucle:
en moyenne, il faudra moins de deux itérations, et la sélection sera uniforme.
Edit: Si votre RNG est cher, vous pouvez limiter le nombre d'itérations de la façon suivante:
Avec cette version, il est hautement improbable que la boucle est pris plus d'une fois (moins d'une chance sur 2^100, c'est à dire beaucoup moins que la probabilité que la machine hôte spontanément prend feu dans la prochaine seconde qui suit). D'autre part, la
mod()
opération est coûteuse en termes de calcul, de sorte que cette version est probablement plus lent que le précédent, à moins que lerandomSource
instance est extrêmement lente.java.security.SecureRandom
qui, sur mon PC, semble sortie d'un peu plus de 4 Mo de alea par seconde. Cela dépend de l'implémentation de Java (ici Sun/Oracle Java 1.6.0_26), l'architecture (Intel Core2, 2.4 GHz, mode 64 bits) et le système d'exploitation (Linux).SecureRandom
sur un système Linux avec OpenJDK 8 et et un core i7-6700 CPU @ 3.40 GHz × 8 processeur. Selon les résultats du test, la première et donc la méthode la plus simple est de deux à trois fois plus vite.La méthode suivante utilise la
BigInteger(int numBits, Random rnd)
constructeur et rejette le résultat si il est plus grand que la valeur spécifiée n.L'inconvénient c'est que le constructeur est appelé un nombre quelconque de fois, mais dans le pire des cas (n est que très légèrement supérieure à une puissance de 2) le nombre d'appels au constructeur devrait être seulement 2 fois.
L'approche la plus simple (par un assez long chemin) serait d'utiliser le spécifiée constructeur pour générer un nombre aléatoire avec le bon nombre de bits (
floor(log2 n) + 1
), et de le jeter ensuite si il est plus grand que n. Dans le pire des cas possible (par exemple un nombre dans l'intervalle [0, 2n + 1), vous allez jeter juste moins de la moitié des valeurs que vous créez, en moyenne.Pourquoi ne pas construire un hasard BigInteger, puis la construction d'un BigDecimal-il ?
Il y a un constructeur en BigDecimal :
public BigDecimal(BigInteger unscaledVal, int scale)
qui semble pertinente ici, non ? Donnez-lui un hasard BigInteger et une échelle aléatoire de type int, et vous aurez un hasard BigDecimal. Non ?Ici est de savoir comment je le fais dans une classe appelée Generic_BigInteger disponible via:
Andy Turner Générique Code Source de la Page Web
Suffit d'utiliser modulaire réduction
Compiler ce code F# dans une DLL et vous pouvez aussi y faire référence dans votre C# /VB.NET les programmes