Java - Random number(난수) 생성하는 방법

JS · 30 Jun 2020

Java에서 다음을 이용하여 random 숫자(난수)를 생성할 수 있습니다.

  • Math.random()
  • Random
  • Apache commons-math3 라이브러리

보통 Math.random()과 Random을 이용하면 되고 필요에 따라서 commons-math3 라이브러리를 사용하시면 됩니다.

Math.random()으로 난수 생성

Math.random()는 static 메소드로, 0 이상 1 미만의 double을 무작위로 리턴합니다.

// Math.java
public static double random()

다음과 같이 5번을 호출하면 모두 다른 숫자가 리턴됩니다.

for (int i = 0; i < 5; i++) {
    System.out.println(Math.random());
}

Output:

0.18483327372551328
0.4999614694230884
0.2758430606141382
0.8476940006649069
0.8567665839943789

만약 random으로 발생하는 숫자의 범위를 정해주고 싶다면 다음처럼 구현하면 됩니다.

다음 코드는 10에서 100 사이의 숫자를 무작위로 리턴합니다.

double min = 10;
double max = 100;
double random = (int) ((Math.random() * (max - min)) + min);
System.out.println(random);

Output:

17.0

만약 double이 아닌 int를 얻고 싶다면 다음과 같이 형변환을 해주면 됩니다.

int min = 10;
int max = 100;
int random = (int) ((Math.random() * (max - min)) + min);
System.out.println(random);

Output:

32

Random 으로 난수 생성

java.util.Random은 난수를 생성하는데 사용되는 클래스입니다.

Random은 다음과 같이 생성할 수 있습니다.

Random random = new Random();

그리고 nextInt()를 호출하면 Int형의 난수가 생성됩니다. 숫자의 범위는 32bit로 표현 가능한 모든 Integer가 리턴될 수 있습니다.

Random random = new Random();
System.out.println(random.nextInt());
System.out.println(random.nextInt());
System.out.println(random.nextInt());
System.out.println(random.nextInt());

Output:

549303722
1433650828
1294409735
1717699611

어떤 숫자 미만의 난수만 생성하고 싶다면 다음과 같이 인자로 경계값을 전달하면 됩니다.

int bound = 100;
System.out.println(random.nextInt(bound));
System.out.println(random.nextInt(bound));

Output:

46
99

Double, Float, Boolean에 대한 난수 생성

nextInt()외에 다른 자료형들에 대한 난수도 생성할 수 있습니다.

  • nextDouble() : 0과 1사이의 Double 난수 리턴
  • nextFloat() : 0과 1사이의 Float 난수 리턴
  • nextLong() : Long 타입의 난수 리턴
  • nextBoolean() : 무작위로 True or False 리턴

Random의 Seed는 무엇인가?

사실 Java는 난수를 랜덤으로 생성하는 것이 아닙니다. 어떤 알고리즘에 따라서 순차적으로 숫자를 계산하고 그 값을 난수로 리턴하는 것입니다.

실제로 Random을 사용하면 동일한 숫자가 나오지 않습니다. 그 이유는 Random 객체를 만들 때 초기값이 매번 달라지기 때문에 난수가 생성되는 패턴이 달라지기 때문입니다. 여기서 말하는 초기값을 seed라고 합니다.

Random 클래스의 생성자는 인자로 seed를 받습니다. 만약 동일한 seed를 입력하면 항상 동일한 패턴의 난수를 생성합니다.

// Random.java
public Random(long seed)

아래 코드를 보시면 2개의 Random객체를 만들 때 동일한 seed를 입력하였습니다. 생성된 난수를 보면 동일한 난수가 생성되는 것을 볼 수 있습니다. 시간이 지나도 이 패턴으로 난수가 생성됩니다.

Random random1 = new Random(10);
Random random2 = new Random(10);

System.out.println("r1 : " + random1.nextInt());
System.out.println("r2 : " + random2.nextInt());

Output:

r1 : -1157793070
r2 : -1157793070

위의 예제에서는 new Random()으로 객체를 생성하였습니다. 그리고 이렇게 생성한 객체가 생성하는 난수를 보면 실행할 때마다 다른 패턴의 난수를 생성하는 것을 볼 수 있습니다.

이유는 다음과 같이 Random()은 시간에 따라 seed가 달라지도록 구현되었기 때문입니다.

public Random() {
    this(seedUniquifier() ^ System.nanoTime());
}

public Random(long seed) {
    if (getClass() == Random.class)
        this.seed = new AtomicLong(initialScramble(seed));
    else {
        // subclass might have overriden setSeed
        this.seed = new AtomicLong();
        setSeed(seed);
    }
}

따라서, new Random()으로 난수를 생성하면 겹치는 일이 거의 발생하지 않게 됩니다.

Apache commons-math3 라이브러리를 이용하여 난수 생성

commons-math3 라이브러리를 이용하여 난수를 생성할 수 있습니다.

Gradle 프로젝트에서 라이브러리를 사용하려면 build.gradle의 dependencies에 다음과 같이 추가하면 됩니다.

dependencies {
  compile group: 'org.apache.commons', name: 'commons-math3', version: '3.6.1'
  ...
}

다음과 같이 int에 대한 난수를 생성할 수 있습니다.

int randomInt = new RandomDataGenerator().getRandomGenerator().nextInt();

범위를 지정하려면 다음과 같이 하면 됩니다. 다음 코드는 leftLimit에서 rightLimit 사이의 숫자를 무작위로 생성합니다.

int leftLimit = 100;
int rightLimit = 120;
int randomInt = new RandomDataGenerator().nextInt(leftLimit, rightLimit);
System.out.println(randomInt);

Output:

112

Double에 대한 난수는 다음과 같이 생성할 수 있습니다.

double randomDouble = new RandomDataGenerator().getRandomGenerator().nextDouble();

범위를 지정하려면 다음과 같이 하면 됩니다.

double leftLimit = 1D;
double rightLimit = 100D;
double randomDouble = new RandomDataGenerator().nextUniform(leftLimit, rightLimit);

Long의 경우 다음과 같이 난수를 생성하거나 범위를 지정할 수 있습니다.

long randomeLong = new RandomDataGenerator().getRandomGenerator().nextLong();

int leftLimit = 100;
int rightLimit = 120;
randomeLong = new RandomDataGenerator().nextLong(leftLimit, rightLimit);
댓글을 보거나 쓰려면 이 버튼을 눌러주세요.
codechachaCopyright ©2019 codechacha