Klasa Random ma metodę generowania losowego int w podanym zakresie. Na przykład:
Random r = new Random();
int x = r.nextInt(100);
To wygenerowałoby liczbę int większą lub równą 0 i mniejszą niż 100. Dokładnie to samo chciałbym zrobić z liczbą długą.
long y = magicRandomLongGenerator(100);
Klasa losowa ma tylko nextLong (), ale nie pozwala na ustawienie zakresu.
java
random
range
long-integer
Vilius Normantas
źródło
źródło
java.util.Random
używa tylko dystrybucji 48-bitowej (zobacz szczegóły implementacji), więc nie będzie miała normalnej dystrybucji.Odpowiedzi:
Począwszy od Java 7 (lub Android API Level 21 = 5.0+) możesz bezpośrednio użyć
ThreadLocalRandom.current().nextLong(n)
(dla 0 ≤ x <n) iThreadLocalRandom.current().nextLong(m, n)
(dla m ≤ x <n). Zobacz odpowiedź @Alex , aby uzyskać szczegółowe informacje.Jeśli utkniesz z Javą 6 (lub Androidem 4.x), musisz skorzystać z zewnętrznej biblioteki (np.
org.apache.commons.math3.random.RandomDataGenerator.getRandomGenerator().nextLong(0, n-1)
Zobacz odpowiedź @mawaldne ) lub zaimplementować własnąnextLong(n)
.Według https://docs.oracle.com/javase/1.5.0/docs/api/java/util/Random.html
nextInt
jest zaimplementowany jakoMożemy więc zmodyfikować to, aby wykonać
nextLong
:źródło
rng.nextLong() % n
da jednolite wartości (załóżmy, że wszystkie bity są dobre). Jeśli chcesz, możesz zignorować tę część.m <= x <= n
, jak zmodyfikowałbyś swoje rozwiązanie?m
orazn
może być uzyskane z wykorzystaniem liczby losowej między0
an-m
, a następnie dodaćm
.ThreadLocalRandom
ThreadLocalRandom
manextLong(long bound)
metodę.Ma również,
nextLong(long origin, long bound)
jeśli potrzebujesz innego źródła niż 0. Podaj początek (włącznie) i granicę (wyłączność).SplittableRandom
ma te samenextLong
metody i pozwala wybrać ziarno, jeśli chcesz uzyskać powtarzalną sekwencję liczb.źródło
Standardową metodą generowania liczby (bez metody narzędziowej) w zakresie jest po prostu użycie liczby podwójnej z zakresem:
da ci wartość długą od 0 (włącznie) do zakresu (wyłączność). Podobnie, jeśli chcesz liczbę między x a y:
daje długi od 1234567 (włącznie) do 123456789 (ekskluzywny)
Uwaga: sprawdź nawiasy, ponieważ rzutowanie na długie ma wyższy priorytet niż mnożenie.
źródło
bound
też być mniejsza od największej liczby całkowitej, którą można zakodować w postaci podwójnej, 2 ^ 53.Powyższe metody działają świetnie. Jeśli używasz apache commons (org.apache.commons.math.random), sprawdź RandomData. Ma metodę: nextLong (długa dolna, długa górna)
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)
źródło
Użyj operatora „%”
Używając operatora „%”, bierzemy resztę po podzieleniu przez maksymalną wartość. Pozostają nam tylko liczby od 0 (włącznie) do dzielnika (wyłączne).
Na przykład:
źródło
if (max == min)
if (nextLong() >= 0)
min = 0
amax = 2 * (MAX_LONG / 3)
, to jesteś dwa razy częściej, aby uzyskać wartość[0, MAX_LONG / 3]
, jak mają się jeden w[MAX_LONG / 3, 2 * (MAX_LONG / 3)]
.nextLong
zwraca wartość ujemną, reszta będzie ujemna, a wartość będzie poza zakresem.Dalsze ulepszanie odpowiedzi KennyTM: Implementacja podklasy uwzględniająca rzeczywistą implementację w Javie 8 to:
źródło
if ((bound & m) == 0) { r = (bound * r) >> (Long.SIZE - 1); }
pierwsze, za pomocą testów jednostkowych łatwo jest wykazać, że w rzeczywistości nie daje to liczb z zakresu [0, związane). Po drugie, jest to niepotrzebnie skomplikowane:r = r & m
przyniosłoby pożądany rezultat, i to właśnie robi obecna implementacja Java 8. Możliwe, że implementacja była inna, gdy została napisana ta odpowiedź, ale nie mogło być to, co pokazano.Jeśli chcesz mieć równomiernie rozłożoną długość pseudolosową w zakresie [0,
m
), spróbuj użyć operatora modulo i metody wartości bezwzględnej w połączeniu znextLong()
metodą, jak pokazano poniżej:Gdzie
rand
jest twój losowy obiekt.Operator modulo dzieli dwie liczby i wyświetla pozostałą część tych liczb. Na przykład,
3 % 2
to1
, ponieważ pozostała część 3 i 2, jest 1.Ponieważ
nextLong()
generuje równomiernie rozłożoną długość pseudolosową w zakresie [- (2 ^ 48), 2 ^ 48) (lub gdzieś w tym zakresie), będziesz musiał wziąć wartość bezwzględną. Jeśli tego nie zrobisz, modulonextLong()
metody ma 50% szans na zwrócenie wartości ujemnej, która jest poza zakresem [0,m
).To, czego początkowo zażądałeś, było równomiernie rozłożonym pseudolosowym długością w zakresie [0,100). Robi to następujący kod:
źródło
Co powiesz na to:
?
źródło
Poniższa metoda zwróci wartość od 10000000000 do 9999999999
źródło
Z API Java 8
Rzeczywistą implementację można byłoby łatwiej pobrać z dokumentu API https://docs.oracle.com/javase/8/docs/api/java/util/Random.html#longs-long-long-long - używają go do generuje strumień długich. Twoje pochodzenie może mieć wartość „0”, jak w pytaniu.
źródło
Ze strony w Random :
Więc jeśli chcesz uzyskać
Long
, nie uzyskasz już pełnego zakresu 64-bitowego.Sugerowałbym, że jeśli masz zakres zbliżony do potęgi 2, zbuduj
Long
jak w tym fragmencie, w ten sposób:aby na przykład uzyskać zakres 35 bitów.
źródło
Metody wykorzystujące
r.nextDouble()
powinny wykorzystywać:źródło
źródło
Random
instancji w trybie hoc, nie powinieneś łapaćThrowable
s ani innych wyjątków, jeśli nie są potrzebne, powinieneś rejestrować błędy za pomocą jakiegoś frameworka logowania (np. SLF4J) zamiast używaćprintStackTrace
.Jeśli możesz korzystać ze strumieni Java, możesz spróbować następujących rozwiązań:
Spowoduje to wygenerowanie liczb w podanym zakresie na długie długości.
źródło
To powinno działać
źródło
// użyj czasu systemowego jako wartości początkowej, aby uzyskać dobrą liczbę losową
// Pętla, aż uzyskasz liczbę większą lub równą 0 i mniejszą niż n
źródło
n
jest 1 lub powiedzmy 2? Pętla wykona wiele iteracji.