본문 바로가기

StackOverflow

[Java] 일정 범위 이내의 정수인 난수를 자바에서는 어떻게 만들어야 하나요?

http://stackoverflow.com/questions/363681/generating-random-integers-in-a-range-with-java


Q: 일정 범위 이내의 정수인 난수를 자바에서는 어떻게 만들어야 하나요?

저는 자바에서 정수인 난수를 생성하려고 합니다. 그리고 범위는 일정 범위 이내여야만 하죠. 예를 들면, 제가 정한 범위가 5~10이라면 최소 숫자는 5이고, 최대 숫자는 10입니다. 이 범위 이내 숫자라면 제가 정한 조건에 맞습니다.

자바에서, Math클래스의 random()메소드가 0.0에서 1.0 사이의 double 값을 반환합니다. Random클래스에서는 nextInt(int n)메소드를 쓰면 0에서 n 까지 범위의 정수를 반환합니다. 일정 범위 이내의 랜덤 정수를 반환하는 메소드는 찾지 못했습니다.

저는 아래와 같은 두 가지 방법을 써봤는데, 아직 문제가 있습니다.

방법 1:

randomNum = minimum + (int)(Math.random()*maximum); 

문제: randomNum에 할당 된 값이 maximum보다 큽니다.


방법 2:

Random rn = new Random();
int n = maximum - minimum + 1;
int i = rn.nextInt() % n;
randomNum =  minimum + i;

문제: randomNum에 할당 된 값이 minimum보다 작습니다.

이 문제를 어떻게 해결하면 좋을까요? 아래와 같은 글을 찾아보았지만, 문제를 해결하지는 못했습니다.

(질문자: user42155)



A: 자바 1.7 이전 버전에서, 일반적으로는 아래와 같이 하면 됩니다.

import java.util.Random;

/**
 * min 과 max 범위 이내의 수도 랜덤값을 리턴.
 * min 과 max 값의 차이는 아래 값 까지 가능.
 * <code>Integer.MAX_VALUE - 1</code>.
 *
 * @param min 최소 값
 * @param max 최대 값. 반드시 min 보다 커야 함.
 * @return 최소 값과 최대 값 범위 이내의 정수.
 * @see java.util.Random#nextInt(int)
 */
public static int randInt(int min, int max) {

    // 주의: 이 코드는 (의도적으로) 위에서 설명된 대로 동작하지 않는데,
    // 이 코드를 복사해서 쓰는 사람들은 Random 값을 어떻게 초기화 해야 할 지 고려해야 함.
    // Random의 초기화는 이 질문의 범위에서 벗어나지만, 
    // 괜찮은 해결책 중 하나는 Random 필드를 하나 만든 뒤 초기화 하고, 그것을 계속 이용하는 것.
    // 아니면 ThreadLocalRandom (Java 1.7 이상)을 이용할 것.
    Random rand;

    // nextInt는 정상적인 경우 최대 값을 포함하지 않기 때문에, 1을 더함.
    int randomNum = rand.nextInt((max - min) + 1) + min;

    return randomNum;
}


관련 자바 문서를 읽어보세요. 현업에서는 java.util.Random를 java.lang.Math.random()보다 많이 이용합니다.

몇몇 경우에는 "바퀴를 다시 발명할 필요 없이" (역주: 이미 완성되어 있는 것을 다시 만들 필요 없이. reinventing the wheel은 이미 만들어진 어떤 것이 있다 하더라도, 학습 등의 이유로 새롭게 그것을 만드는 것을 의미하기도 합니다) 표준 API를 이용하여 해당 동작을 할 수 있습니다.

자바 1.7 이후 버전에서는 아래 메소드를 이용하여 시드 값 초기화도 필요 없이 원하는 동작을 수행할 수 있습니다.

import java.util.concurrent.ThreadLocalRandom;

// nextInt 는 정상적인 경우 최대 값을 포함하지 않기 때문에,
// 1을 더하는 과정 추가
ThreadLocalRandom.current().nextInt(min, max + 1);

(답변자: Greg Case)


_

I am trying to generate a random integer with Java, but random in a specific range. For example, my range is 5-10, meaning that 5 is the smallest possible value the random number can take, and 10 is the biggest. Any other number in between these numbers is possible to be a value, too.

In Java, there is a method random() in the Math class, which returns a double value between 0.0 and 1.0. In the class Random there is a method nextInt(int n), which returns a random integer value in the range of 0 (inclusive) and n (exclusive). I couldn't find a method, which returns a random integer value between two numbers.

I have tried the following things, but I still have problems: (minimum and maximum are the smallest and biggest numbers).

Solution 1:

randomNum = minimum + (int)(Math.random()*maximum); 

Problem: randomNum is assinged values numbers bigger than maximum.

Solution 2:

Random rn = new Random();
int n = maximum - minimum + 1;
int i = rn.nextInt() % n;
randomNum =  minimum + i;

Problem: randomNum is assigned values smaller than minimum.

How do I solve this problem?

I have tried also browsing through the archive and found:

But I couldn't solve the problem.

shareeditflag

_

1794down vote
+150

The standard way to do this (before Java 1.7) is as follows:

import java.util.Random;

/**
 * Returns a pseudo-random number between min and max, inclusive.
 * The difference between min and max can be at most
 * <code>Integer.MAX_VALUE - 1</code>.
 *
 * @param min Minimum value
 * @param max Maximum value.  Must be greater than min.
 * @return Integer between min and max, inclusive.
 * @see java.util.Random#nextInt(int)
 */
public static int randInt(int min, int max) {

    // NOTE: This will (intentionally) not run as written so that folks
    // copy-pasting have to think about how to initialize their
    // Random instance.  Initialization of the Random instance is outside
    // the main scope of the question, but some decent options are to have
    // a field that is initialized once and then re-used as needed or to
    // use ThreadLocalRandom (if using at least Java 1.7).
    Random rand;

    // nextInt is normally exclusive of the top value,
    // so add 1 to make it inclusive
    int randomNum = rand.nextInt((max - min) + 1) + min;

    return randomNum;
}

See the relevant JavaDoc. In practice, the java.util.Random class is often preferable tojava.lang.Math.random().

In particular, there is no need to reinvent the random integer generation wheel when there is a straightforward API within the standard library to accomplish the task.

In Java 1.7 or later, the following method is even more straightforward as long as there is no need to explicitly set the initial seed:

import java.util.concurrent.ThreadLocalRandom;

// nextInt is normally exclusive of the top value,
// so add 1 to make it inclusive
ThreadLocalRandom.current().nextInt(min, max + 1);
shareeditflag