La classe aléatoire a une méthode pour générer des int aléatoires dans une plage donnée. Par exemple:
Random r = new Random();
int x = r.nextInt(100);
Cela générerait un nombre entier supérieur ou égal à 0 et inférieur à 100. J'aimerais faire exactement la même chose avec un nombre long.
long y = magicRandomLongGenerator(100);
La classe aléatoire n'a que nextLong (), mais elle ne permet pas de définir range.
java
random
range
long-integer
Vilius Normantas
la source
la source
java.util.Random
utilise uniquement une distribution 48 bits (voir les détails de l'implémentation), donc elle n'aura pas de distribution normale.Réponses:
À partir de Java 7 (ou Android API Level 21 = 5.0+), vous pouvez utiliser directement
ThreadLocalRandom.current().nextLong(n)
(pour 0 ≤ x <n) etThreadLocalRandom.current().nextLong(m, n)
(pour m ≤ x <n). Voir la réponse de @Alex pour plus de détails.Si vous êtes bloqué avec Java 6 (ou Android 4.x), vous devez utiliser une bibliothèque externe (par exemple
org.apache.commons.math3.random.RandomDataGenerator.getRandomGenerator().nextLong(0, n-1)
, voir la réponse de @mawaldne ), ou implémenter la vôtrenextLong(n)
.Selon https://docs.oracle.com/javase/1.5.0/docs/api/java/util/Random.html
nextInt
est implémenté commeNous pouvons donc modifier ceci pour effectuer
nextLong
:la source
rng.nextLong() % n
donnera des valeurs uniformes (en supposant que tous les bits sont bons). Vous pouvez ignorer cette partie si vous le souhaitez.m <= x <= n
, comment modifieriez-vous votre solution?m
etn
peut être obtenu avec un nombre aléatoire entre0
etn-m
, puis additionnezm
.ThreadLocalRandom
ThreadLocalRandom
a unenextLong(long bound)
méthode.Il a également
nextLong(long origin, long bound)
si vous avez besoin d'une origine autre que 0. Passez l'origine (inclus) et la borne (exclusive).SplittableRandom
a les mêmesnextLong
méthodes et vous permet de choisir une graine si vous voulez une séquence reproductible de nombres.la source
La méthode standard pour générer un nombre (sans méthode utilitaire) dans une plage consiste simplement à utiliser le double avec la plage:
vous donnera un long entre 0 (inclus) et intervalle (exclusif). De même si vous voulez un nombre entre x et y:
vous donnera un long de 1234567 (inclus) à 123456789 (exclusif)
Remarque: vérifiez les parenthèses, car la conversion en long a une priorité plus élevée que la multiplication.
la source
bound
devra être inférieur au plus grand entier pouvant être encodé dans un double, 2 ^ 53.Les méthodes ci-dessus fonctionnent très bien. Si vous utilisez apache commons (org.apache.commons.math.random) consultez RandomData. Il a une méthode: nextLong (long inférieur, long supérieur)
http://commons.apache.org/math/userguide/random.html
http://commons.apache.org/math/api-1.1/org/apache/commons/math/random/RandomData.html#nextLong(long,%20long)
la source
Utilisez l'opérateur '%'
En utilisant l'opérateur '%', nous prenons le reste lorsqu'il est divisé par votre valeur maximale. Cela nous laisse avec seulement des nombres de 0 (inclus) au diviseur (exclusif).
Par exemple:
la source
if (max == min)
if (nextLong() >= 0)
min = 0
etmax = 2 * (MAX_LONG / 3)
, alors vous êtes deux fois plus susceptible d'obtenir une valeur[0, MAX_LONG / 3]
que vous l'êtes[MAX_LONG / 3, 2 * (MAX_LONG / 3)]
.nextLong
renvoie une valeur négative, le reste sera négatif et la valeur sera en dehors de la plage.Améliorer encore la réponse de kennytm: Une implémentation de sous-classe prenant en compte l'implémentation réelle dans Java 8 serait:
la source
if ((bound & m) == 0) { r = (bound * r) >> (Long.SIZE - 1); }
Premièrement, il est facile de montrer avec des tests unitaires que cela ne produit pas réellement de nombres dans la plage [0, lié). Deuxièmement, c'est inutilement élaboré: celar = r & m
permettrait d'obtenir le résultat souhaité, et c'est essentiellement ce que fait l'implémentation actuelle de Java 8. Il est possible que l'implémentation ait été différente lorsque cette réponse a été écrite, mais cela ne peut pas avoir été ce qui est montré.Si vous voulez un long pseudo-aléatoire uniformément distribué dans la plage de [0,
m
), essayez d'utiliser l'opérateur modulo et la méthode de la valeur absolue combinés avec lanextLong()
méthode comme indiqué ci-dessous:Où
rand
est votre objet aléatoire.L'opérateur modulo divise deux nombres et génère le reste de ces nombres. Par exemple,
3 % 2
est1
parce que le reste de 3 et 2 est 1.Puisque
nextLong()
génère un long pseudo-aléatoire uniformément distribué dans la plage de [- (2 ^ 48), 2 ^ 48) (ou quelque part dans cette plage), vous devrez en prendre la valeur absolue. Sinon, le modulo de lanextLong()
méthode a 50% de chances de renvoyer une valeur négative, qui est hors de la plage [0,m
).Ce que vous avez initialement demandé était un long pseudo-aléatoire uniformément distribué dans la gamme de [0,100). Le code suivant le fait:
la source
Que dis-tu de ça:
?
la source
La méthode ci-dessous vous renverra une valeur comprise entre 10000000000 et 9999999999
la source
Depuis Java 8 API
Il pourrait être plus facile de prendre la mise en œuvre réelle à partir de la documentation API https://docs.oracle.com/javase/8/docs/api/java/util/Random.html#longs-long-long-long- ils l'utilisent pour générer un flux long. Et votre origine peut être "0" comme dans la question.
la source
À partir de la page sur Random :
Donc, si vous voulez obtenir un
Long
, vous déjà pas la gamme complète de 64 bits.Je suggérerais que si vous avez une portée proche d'une puissance de 2, vous construisez le
Long
comme dans cet extrait de code, comme ceci:pour obtenir une plage de 35 bits, par exemple.
la source
Les méthodes utilisant le
r.nextDouble()
devraient utiliser:la source
la source
Random
instances à coup sûr, vous ne devriez pas attraper desThrowable
exceptions ou d'autres exceptions si cela n'est pas nécessaire, vous devriez enregistrer les erreurs avec une sorte de cadre de journalisation (c'est-à-dire SLF4J) au lieu d'utiliserprintStackTrace
.Si vous pouvez utiliser des flux Java, vous pouvez essayer ce qui suit:
Cela générera des nombres dans la plage donnée pour les longs.
la source
Cela devrait fonctionner
la source
// utilise l'heure système comme valeur de départ pour obtenir un bon nombre aléatoire
// Boucle jusqu'à obtenir un nombre supérieur ou égal à 0 et inférieur à n
la source
n
vaut 1 ou disons 2? La boucle effectuera de nombreuses itérations.