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);
Related Posts
- Java - Unsupported class file major version 61 에러
- Java - String.matches()로 문자열 패턴 확인 및 다양한 예제 소개
- Java - 문자열 공백제거 (trim, replace)
- Java - replace()와 replaceAll()의 차이점
- Java - ArrayList 초기화, 4가지 방법
- Java - 배열 정렬(Sorting) (오름차순, 내림차순)
- Java - 문자열(String)을 비교하는 방법 (==, equals, compare)
- Java - StringBuilder 사용 방법, 예제
- Java - 로그 출력, 파일 저장 방법 (Logger 라이브러리)
- Java IllegalArgumentException 의미, 발생 이유
- Java - NullPointerException 원인, 해결 방법
- Seleninum의 ConnectionFailedException: Unable to establish websocket connection 해결
- Java - compareTo(), 객체 크기 비교
- Java - BufferedWriter로 파일 쓰기
- Java - BufferedReader로 파일 읽기
- Java charAt() 함수 알아보기
- Java - BigInteger 범위, 비교, 연산, 형변환
- Java contains()로 문자(대소문자 X) 포함 확인
- Java - Set(HashSet)를 배열로 변환
- Java - 문자열 첫번째 문자, 마지막 문자 확인
- Java - 문자열 한글자씩 자르기
- Java - 문자열 단어 개수 가져오기
- Java - 1초마다 반복 실행
- Java - 배열을 Set(HashSet)로 변환
- Java - 여러 Set(HashSet) 합치기
- Java - 명령행 인자 입력 받기
- Java - 리스트 역순으로 순회, 3가지 방법
- Java - 특정 조건으로 리스트 필터링, 3가지 방법
- Java - HashMap 모든 요소들의 합계, 평균 계산
- Java - 특정 조건으로 HashMap 필터링
- Java - 싱글톤(Singleton) 패턴 구현
- Java - 숫자 왼쪽에 0으로 채우기
- Java - String 배열 초기화 방법
- Java - 정렬된 순서로 Map(HashMap) 순회
- Java - HashMap에서 key, value 가져오기