A classe Random possui um método para gerar int aleatório em um determinado intervalo. Por exemplo:
Random r = new Random();
int x = r.nextInt(100);
Isso geraria um número int maior ou igual a 0 e menor que 100. Eu gostaria de fazer exatamente o mesmo com o número longo.
long y = magicRandomLongGenerator(100);
A classe aleatória possui apenas nextLong (), mas não permite definir o intervalo.
java
random
range
long-integer
Vilius Normantas
fonte
fonte
java.util.Random
usa apenas uma distribuição de 48 bits (consulte os detalhes da implementação), portanto não terá uma distribuição normal.Respostas:
A partir do Java 7 (ou Android API Level 21 = 5.0+), você poderia usar diretamente
ThreadLocalRandom.current().nextLong(n)
(para 0 ≤ x <n) eThreadLocalRandom.current().nextLong(m, n)
(para m ≤ x <n). Consulte a resposta do @Alex para obter detalhes.Se você está com o Java 6 (ou Android 4.x), precisa usar uma biblioteca externa (por exemplo
org.apache.commons.math3.random.RandomDataGenerator.getRandomGenerator().nextLong(0, n-1)
, consulte a resposta de @mawaldne ) ou implementar sua próprianextLong(n)
.De acordo com https://docs.oracle.com/javase/1.5.0/docs/api/java/util/Random.html,
nextInt
é implementado comoPortanto, podemos modificar isso para executar
nextLong
:fonte
rng.nextLong() % n
fornecerá valores uniformes (suponha que todos os bits sejam bons). Você pode ignorar essa parte, se quiser.m <= x <= n
, como você modificaria sua solução?m
en
pode ser obtido com um número aleatório entre0
en-m
, em seguida, adicionem
.ThreadLocalRandom
ThreadLocalRandom
tem umnextLong(long bound)
métodoEle também possui
nextLong(long origin, long bound)
se você precisar de uma origem diferente de 0. Passe a origem (inclusive) e o limite (exclusivo).SplittableRandom
tem os mesmosnextLong
métodos e permite que você escolha uma semente se você quiser uma sequência reprodutível de números.fonte
O método padrão para gerar um número (sem um método utilitário) em um intervalo é apenas usar o dobro com o intervalo:
fornecerá um tempo entre 0 (inclusive) e intervalo (exclusivo). Da mesma forma, se você deseja um número entre x e y:
fornecerá um longo tempo de 1234567 (inclusive) a 123456789 (exclusivo)
Nota: verifique os parênteses, porque a conversão para long tem prioridade mais alta que a multiplicação.
fonte
bound
terá que ser menor que o maior número inteiro que pode ser codificado em um duplo, 2 ^ 53.Os métodos acima funcionam muito bem. Se você estiver usando o apache commons (org.apache.commons.math.random), consulte RandomData. Ele tem um método: nextLong (long lower, long upper)
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)
fonte
Use o operador '%'
Usando o operador '%', pegamos o restante quando dividido pelo seu valor máximo. Isso nos deixa com apenas números de 0 (inclusive) ao divisor (exclusivo).
Por exemplo:
fonte
if (max == min)
if (nextLong() >= 0)
min = 0
emax = 2 * (MAX_LONG / 3)
, então você tem duas vezes mais chances de obter um valor do[0, MAX_LONG / 3]
que um[MAX_LONG / 3, 2 * (MAX_LONG / 3)]
.nextLong
retornar um valor negativo, o restante será negativo e o valor estará fora do intervalo.Melhorando ainda mais a resposta do kennytm: Uma implementação de subclasse levando em consideração a implementação real no Java 8 seria:
fonte
if ((bound & m) == 0) { r = (bound * r) >> (Long.SIZE - 1); }
Primeiro, é fácil mostrar com testes de unidade que isso realmente não produz números no intervalo [0, vinculado). Segundo, é desnecessariamente elaborado:r = r & m
atingiria o resultado desejado, e é basicamente isso que a implementação atual do Java 8 faz. É possível que a implementação tenha sido diferente quando essa resposta foi escrita, mas não pode ter sido o que é mostrado.Se você deseja um pseudoaleatório uniformemente distribuído no intervalo de [0,
m
), tente usar o operador modulo e o método do valor absoluto combinado com onextLong()
método conforme mostrado abaixo:Onde
rand
está o seu objeto aleatório.O operador módulo divide dois números e gera o restante desses números. Por exemplo,
3 % 2
é1
porque o restante de 3 e 2 é 1.Como
nextLong()
gera um pseudoaleatório uniformemente distribuído no intervalo de [- (2 ^ 48), 2 ^ 48) (ou em algum lugar desse intervalo), você precisará obter o valor absoluto dele. Caso contrário, o módulo donextLong()
método tem 50% de chance de retornar um valor negativo, que está fora do intervalo [0,m
).O que você solicitou inicialmente foi um pseudoaleatório uniformemente distribuído, no intervalo de [0,100). O código a seguir faz isso:
fonte
Que tal agora:
?
fonte
O método abaixo retornará um valor entre 10000000000 e 9999999999
fonte
Da API do Java 8
Poderia ser mais fácil obter a implementação real do documento da API https://docs.oracle.com/javase/8/docs/api/java/util/Random.html#longs-long-long-long- eles estão usando isso para gerar fluxo de longos. E sua origem pode ser "0", como na pergunta.
fonte
Na página Random :
Portanto, se você deseja obter um
Long
, você já não terá o intervalo completo de 64 bits.Eu sugeriria que, se você tem um alcance que cai perto de uma potência de 2, você cria o
Long
como nesse snippet, assim:para obter um intervalo de 35 bits, por exemplo.
fonte
Os métodos usando o
r.nextDouble()
devem usar:fonte
fonte
Random
instâncias no hoc, não deve capturarThrowable
s ou outras exceções, se não for necessário, deve registrar erros com algum tipo de estrutura de log (por exemplo, SLF4J) em vez de usarprintStackTrace
.Se você pode usar fluxos java, pode tentar o seguinte:
Isso irá gerar números no intervalo especificado por longos.
fonte
Isso deve funcionar
fonte
// use a hora do sistema como valor inicial para obter um bom número aleatório
// Faz loop até obter um número maior ou igual a 0 e menor que n
fonte
n
for 1 ou dizer 2? O loop executará muitas iterações.