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 - java.util.Date를 java.sql.Date로 변환
- Java - 시스템 운영체제(OS) 정보 확인
- Java - 코드 실행 시간 측정
- Java - ArrayList를 String으로 변환
- Java - float을 int로 변환
- Java - float을 String으로 변환
- Java - String을 boolean으로 변환
- Java - XML을 JSON으로 변환
- Java - private 생성자를 사용하는 이유
- Java - non-static method cannot be referenced from a static context
- Java - Object를 byte[]로 변환
- Java - JSON 라이브러리 사용 방법 (JSONObject, JSONArray)
- Java - ZIP 압축, 압축 해제 (zip, unzip)
- Java - byte[] 배열을 File에 저장
- Java - byte[] 배열을 String으로 변환
- Java - 강제로 OutOfMemoryError 발생시키기
- Java - 배열 복사 (deep copy)
- Java - 임시 폴더(Temp directory) 경로 가져오기
- Java에서 쉘 스크립트 실행
- Java - 전화번호 유효성 검사
- Java - File이 존재하는지 확인
- Java - 특정 경로의 하위 파일, 폴더 탐색 (Files.walk)
- Java - ArrayList를 배열로 변환
- Java - List의 중복 제거, 중복 체크 방법
- Java - 여러 배열을 하나로 합치기
- Java - Default Locale 변경
- Java - String이 null인지 empty인지 확인
- Java - 배열을 리스트(ArrayList)로 변환
- Java - 절대값 함수, Math.abs()
- Java - String을 double로 변환
- Java - String을 float으로 변환
- Java - String을 int로 변환
- Java - Random bytes 생성 (Random 16진수 생성)
- Java - 줄바꿈(개행), OS에 맞게 처리하는 방법
- Java - 기본 Logging 라이브러리 소개
- Java - 문자열 뒤집기 (Reverse String)