컴퓨터의 랜덤
술 먹고, 같이 먹은 사람들의 카드를 부채꼴로 펼치면서 식당 종업원에게 카드를 골라달라고 해본적있는가? 고를 확률은 랜덤이라고 할 수 있을까? 식당 종업원이 좋아하는 디자인 취향, 왼손잡이인지 오른손잡이인지에 따라 결과는 치우쳐질 수 있다. 이까지는 누구나 인지하는 사실이다.
“그래! 이건 완전한 랜덤이 아니야!” 계산할 사람을 지목하는데에 네이버 사다리 타기를 이용하기로 했다.
흔히 이렇게 “랜덤성”을 컴퓨터 프로그램에 의존하고는 한다. 뭔가…뭔가 객관적이어 보이니까? 하지만 컴퓨터는 결정론적으로 동작하고, 어떻게 보면 랜덤과는 가장 거리가 멀다. 모든 프로그래밍 언어에는 random()이라는 함수가 있다. 그러면 이들은 어떻게 구현이 된걸까? 만약에 내가 구현한다면 어떻게 랜덤성을 부여할까? 궁금해서 찾아보게되었다.
Java에서 Random을 사용할때 일반적으로 이렇게 사용한다. 여태까지는 이렇게 사용하는데 전혀 문제가 없었다. 상황마다 다른 값이 나왔기 때문이다.
boolean rd = Random().nextInt(10) == 0 // rd는 1/10 확률
상황마다 다른 값이나오는 이유는 java.util.Random()
이 생성될때 현재 시간(ms)으로 시드를 설정했기 때문이다. ms단위로 같은 동작을 실행하지 않은이상 모두 다른 값이 나올 수 밖에 없다.
public class Random implements Serializable
{
private long seed;
public Random() {
this(System.currentTimeMillis());
}
}
Seed?
시드(Seed)라는 것은 뭐고, 왜 설정하는 걸까?
마인크래프트 유저라면 곧바로 감이올 것이다. 마인크래프트는 플레이어가 걸어감에 따라 맵이 무한히 생성되어 펼쳐지는 세계다(JavaEdition 기준). 맵 마다 시드라는게 존재하는데 특정 시드값을 입력하면 똑같은 맵에서 플레이 할 수 있다. 지형이 완전히 동일하게 만들어진다. 그 시드가 이 시드다.
컴퓨터에서 생성하는 난수들은 진정한 의미에서의 난수가 아니라 의사 난수(pseudo-random)이다. 그리고 의사 난수 생성기(Pesudo-random generator)는 이전 값을 기반으로 다음 숫자를 생성하는 형태를 가지고 있다. 최초의 이전값은 궁극적으로 시드다. 따라서 시드가 같으면 몇 번을 뽑더라도 같은 패턴의 숫자들이 나올 것이다.
예시로 시드를 0으로 설정해서 5번 루프를 돌려봤는데, 이렇게 몇 번을 돌려도 같은 [0 8 9 7 5]
배열이 나오게 된다.
import java.util.*
fun main(args: Array<String>) {
val random = Random(0) // Seed is 0
for (i in 0 until 5) {
print("${random.nextInt(10)} ") // 0 8 9 7 5
}
}
참고자료
https://medium.com/code-yoga/random-numbers-are-not-random-701dd2fbc2b8
https://developer.classpath.org/doc/java/util/Random-source.html
'프로그래밍 > General' 카테고리의 다른 글
[CloudFlare] Workers Log 편하게 보는 법 (0) | 2023.02.02 |
---|---|
[AppsScript] 스프레드 시트 Row 업데이트한 날짜 자동으로 적는 법 (0) | 2023.01.11 |
[Windows] Git Bash에 zsh (Oh-my-zsh) 설치해서 꾸미기 (2) | 2022.10.04 |
[batch] Windows 바탕화면에 바로가기 만들기 배치 스크립트 (0) | 2022.09.03 |
[Windows] Git Bash에 tmux 설치해서 사용하기 (0) | 2022.08.29 |