[java] 자바 : 0 <= x <n 범위의 임의의 긴 숫자

Random 클래스에는 주어진 범위에서 random int를 생성하는 메소드가 있습니다. 예를 들면 다음과 같습니다.

Random r = new Random();
int x = r.nextInt(100);

이것은 0 이상 100 이하의 int 숫자를 생성합니다. 긴 숫자와 똑같이하고 싶습니다.

long y = magicRandomLongGenerator(100);

임의 클래스에는 nextLong () 만 있지만 범위를 설정할 수 없습니다.



답변

에서 시작 자바 7 직접 사용할 수 있습니다 (또는 = 5.0 안드로이드 API 레벨 21) ThreadLocalRandom.current().nextLong(n)(≤ X <N 0)과 ThreadLocalRandom.current().nextLong(m, n)(≤ X <N m)입니다. 자세한 내용은 @Alex 의 답변을 참조하십시오 .


Java 6 (또는 Android 4.x) 이 붙어 있다면 외부 라이브러리 (예 : @mawaldne 의 답변 org.apache.commons.math3.random.RandomDataGenerator.getRandomGenerator().nextLong(0, n-1)참조 )를 사용하거나 직접 구현해야합니다 .nextLong(n)

에 따르면 https://docs.oracle.com/javase/1.5.0/docs/api/java/util/Random.html nextInt 로 구현됩니다

 public int nextInt(int n) {
     if (n<=0)
                throw new IllegalArgumentException("n must be positive");

     if ((n & -n) == n)  // i.e., n is a power of 2
         return (int)((n * (long)next(31)) >> 31);

     int bits, val;
     do {
         bits = next(31);
         val = bits % n;
     } while(bits - val + (n-1) < 0);
     return val;
 }

그래서 우리는 이것을 수행하도록 수정할 수 있습니다 nextLong:

long nextLong(Random rng, long n) {
   // error checking and 2^x checking removed for simplicity.
   long bits, val;
   do {
      bits = (rng.nextLong() << 1) >>> 1;
      val = bits % n;
   } while (bits-val+(n-1) < 0L);
   return val;
}


답변

ThreadLocalRandom

ThreadLocalRandom갖는 nextLong(long bound)방법.

long v = ThreadLocalRandom.current().nextLong(100);

nextLong(long origin, long bound)0 이외의 원점이 필요한 경우 도 있습니다 . 원점 (포함) 및 바운드 (제외)를 전달하십시오.

long v = ThreadLocalRandom.current().nextLong(10,100); // For 2-digit integers, 10-99 inclusive.

SplittableRandom동일한 nextLong방법을 사용하고 재현 가능한 일련의 숫자를 원할 경우 시드를 선택할 수 있습니다.


답변

범위에서 숫자를 생성하는 표준 방법 (유틸리티 방법 없음)은 범위와 함께 double을 사용하는 것입니다.

long range = 1234567L;
Random r = new Random()
long number = (long)(r.nextDouble()*range);

0 (포함)과 범위 (제외) 사이의 긴 값을 제공합니다. 마찬가지로 x와 y 사이의 숫자를 원하는 경우 :

long x = 1234567L;
long y = 23456789L;
Random r = new Random()
long number = x+((long)(r.nextDouble()*(y-x)));

1234567 (포함)부터 123456789 (제외)까지의 길이를 제공합니다

참고 : long으로 캐스트하는 것이 곱셈보다 우선 순위가 높으므로 괄호를 확인하십시오.


답변

위의 방법은 훌륭하게 작동합니다. 아파치 커먼즈 (org.apache.commons.math.random)를 사용한다면 RandomData를 확인하십시오. 방법이 있습니다 : 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)


답변

‘%’연산자를 사용하십시오.

resultingNumber = (r.nextLong() % (maximum - minimum)) + minimum;

‘%’연산자를 사용하면 나머지를 최대 값으로 나눌 때 나머지를 가져옵니다. 이것은 0 (제외)부터 제수 (제외)까지의 숫자 만 남습니다.

예를 들면 다음과 같습니다.

public long randLong(long min, long max) {
    return (new java.util.Random().nextLong() % (max - min)) + min;
}


답변

kennyTM의 답변 개선 : Java 8의 실제 구현을 고려한 서브 클래스 구현은 다음과 같습니다.

public class MyRandom extends Random {
  public long nextLong(long bound) {
    if (bound <= 0) {
      throw new IllegalArgumentException("bound must be positive");
    }

    long r = nextLong() & Long.MAX_VALUE;
    long m = bound - 1L;
    if ((bound & m) == 0) { // i.e., bound is a power of 2
      r = (bound * r) >> (Long.SIZE - 1);
    } else {
      for (long u = r; u - (r = u % bound) + m < 0L; u = nextLong() & Long.MAX_VALUE);
    }
    return r;
  }
}


답변

[0, m) 범위에서 균일하게 분포 된 의사 난수를 원하면 모듈로 연산자와 절대 값 방법을 nextLong()아래에 표시된 방법과 결합하여 사용하십시오 .

Math.abs(rand.nextLong()) % m;

rand랜덤 오브젝트는 어디에 있습니까 ?

모듈로 연산자는 두 숫자를 나누고 나머지 숫자를 출력합니다. 예를 들어, 3 % 2이다 1(3)과 (2)의 나머지 하나이기 때문이다.

nextLong()[-(2 ^ 48), 2 ^ 48) 범위 (또는 해당 범위 어딘가)에서 균일하게 분포 된 의사 난수를 생성 하므로 절대 값을 가져와야합니다. 그렇지 않으면 nextLong()메소드 의 모듈로가 50 %의 확률로 [0, m) 범위를 벗어난 음수 값을 리턴합니다 .

처음에 요청한 것은 [0,100) 범위의 균일하게 분포 된 의사 난수입니다. 다음 코드는 그렇게합니다.

Math.abs(rand.nextLong()) % 100;