Math.random () 대 Random.nextInt (int)


135

무엇의 차이는 Math.random() * n하고 Random.nextInt(n)어디 n정수 무엇입니까?


나는 수학을 모른다. 그러나 FindBugs가 당신이 사용하면 불평한다고 알고있다Math.random()
finnw

3
Random에는 정적 메서드가 없으므로 (new Random ()). nextInt (n))을 사용하십시오. Math에서 비슷한 정수를 생성하려면 다음을 사용하십시오. Math.floor ((Math.random () * n) +1);
Dimitri Dewaele

답변:


169

다음은 Gili가 링크 한 Sun 포럼 게시물에서 " 보다 더 효율적이고 편향이 적은 이유"에 대한 자세한 설명 입니다 .Random.nextInt(n)Math.random() * n

Math.random ()은 내부적으로 Random.nextDouble ()을 사용합니다.

Random.nextDouble ()은 Random.next ()를 두 번 사용하여 가수에 대략 균일하게 분포 된 비트를 갖는 double을 생성하므로 0에서 1- (2 ^ -53) 범위로 균일하게 분포됩니다.

Random.nextInt (n)은 평균에서 두 번 미만인 Random.next ()를 사용합니다. 한 번만 사용합니다. 획득 한 값이 MAX_INT 아래의 n의 가장 높은 배수보다 높으면 다시 시도하고 그렇지 않으면 modulo n 값을 반환합니다 (이 값은 MAX_INT 아래의 n의 가장 높은 배수를 초과하는 값이 분포를 왜곡하지 않도록 방지) 0에서 n-1 범위로 균일하게 분포 된 값을 반환합니다.

6으로 스케일하기 전에 Math.random ()의 출력은 균일 분포에서 도출 된 2 ^ 53 개의 가능한 값 중 하나입니다.

6으로 스케일링해도 가능한 값의 개수가 변경되지 않고 int로 캐스팅하면이 값을 6 개의 버킷 (0, 1, 2, 3, 4, 5) 중 하나로 강제합니다. 각 버킷은 다음 중 하나를 포함하는 범위에 해당합니다. 가능한 값 중 1501199875790165 또는 1501199875790166 (6은 2 ^ 53의 제수가 아님). 이것은 충분한 수의 다이스 롤 (또는 충분히 많은 수의 측면을 가진 다이)에 대해 다이가 더 큰 버킷을 향해 편향되어 있음을 나타냅니다.

이 효과가 나타날 때까지 매우 오랜 시간 동안 주사위를 굴릴 것입니다.

Math.random ()도 약 두 배의 처리가 필요하며 동기화 될 수 있습니다.


3
Random.nextInt 및 nextDouble도 동기화 대상입니다.
adrianos

이러한 맥락에서 "편향이 적은"이란 무엇을 의미합니까?
ΦXocę 웃 Пepeúpa ツ

2
@ ΦXocę 웃 Пepeúpa ツ 그것은 단순히 특정 숫자가 다른 숫자보다 더 많이 그려 질 수 있음을 의미합니다. 에서와 같이 다른 숫자보다 일부 숫자를 선택하는 것이 편향되어 있습니다 (따라서 완전히 임의적이지 않거나 충분히 큰 표본 크기 유니폼이 주어짐)
ford prefect

1
해당 스레드에 대한 마지막 주석은 다음과 같이보고합니다. "설명 된 바이어스는 2 ^ 53의 한 부분이지만 사용 된 PRNG의 최대 사이클 길이는 2 ^ 48입니다. 따라서 응용 프로그램에서 볼 수있는 것은 데이터입니다 편견이 아닌 기본 PRNG의 분포 " 이것은 두 가지 방법이 동일하다는 사실을 지적 할 것입니다
디지털 환상

1
@ ΦXocę 웃 Пepeúpaツ교체 6와 함께 5주사위 큐브 : 그것은 "5는 바이어스"입니다. 주사위에 문제가 있음을 알기 전에 주사위를 몇 번 던질 수 있습니다. 랜덤 제너레이터에 문제가 있음을 알기 전에 매우 정교한 철저한 검사를 수행해야합니다.
Dávid Horváth

27

또 다른 중요한 점은 Random.nextInt (n)은 동일한 시드로 두 개의 Random 객체를 만들 수 있기 때문에 반복 가능하다는 것 입니다. Math.random ()에서는 불가능합니다.



0

이 예제에 따르면 Random.nextInt(n)Math.random () * n보다 예측하기 어려운 출력이 있습니다. [정렬되지 않은 배열보다 빠른 정렬 된 배열] [1]에 따르면 Random.nextInt (n)이 예측하기 어렵다고 말할 수 있습니다 .

usingRandomClass : 시간 : 328 마일 초

usingMathsRandom : 시간 : 187 마일 초.

package javaFuction;
import java.util.Random;
public class RandomFuction 
{
    static int array[] = new int[9999];
    static long sum = 0;
    public static void usingMathsRandom() {
        for (int i = 0; i < 9999; i++) {
         array[i] = (int) (Math.random() * 256);
       }

        for (int i = 0; i < 9999; i++) {
            for (int j = 0; j < 9999; j++) {
                if (array[j] >= 128) {
                    sum += array[j];
                }
            }
        }
    }

    public static void usingRandomClass() {
        Random random = new Random();
        for (int i = 0; i < 9999; i++) {
            array[i] = random.nextInt(256);
        }

        for (int i = 0; i < 9999; i++) {
            for (int j = 0; j < 9999; j++) {
                if (array[j] >= 128) {
                    sum += array[j];
                }
            }

        }

    }

    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        usingRandomClass();
        long end = System.currentTimeMillis();
        System.out.println("usingRandomClass " + (end - start));
        start = System.currentTimeMillis();
        usingMathsRandom();
        end = System.currentTimeMillis();
        System.out.println("usingMathsRandom " + (end - start));

    }

}

1
두 번째 루프에서는> = 50을 확인하는데, 이는 50 % 이상의 경우에 해당됩니다. 이로 인해 if 문이 대부분 참이되어 예측하기 쉬워집니다. 결과는 당신의 답변에 찬성하여 편향됩니다
Neuron

오타 실수입니다 ... 두 번째 예에서 128을 만들면 동일한 결과를 얻을 수 있습니다.
jatin Goyal
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.