Random Number(랜덤 숫자)란?

STL 에서의 랜덤 숫자는 무엇을 의미하고 어떻게 구하는지 간단히 알아보자.


랜덤 숫자

랜덤성은 예측 불가능을 의미며 진정한 랜덤성은 오직 자연계에서만 존재한다. 따라서 컴퓨터는 유사 랜덤 순차열만 생성가능하다. 컴퓨터는 결정론적이므로 계산이 주어진 입력 값에 대해 항상 같은 결과를 내놓아야 하므로 컴퓨터로 생성한 숫자는 진정한 의미에서 랜덤일 수 없다. 이것이 컴퓨터는 유사 랜덤 순차열만 생성이 가능한 이유이다.

랜덤 숫자 생성을 위한 몇 가지 통계 개념이 필요하므로 확률, 분포, 엔트로피에 대해서 간단히 알아보자.


확률, 분포, 엔트로피

확률이란, 사건이 일어날 가능성을 포함 0과 1 사이의 값이다. 0은 사건이 결코 일어날 수 없고, 1은 사건이 틀림없이 일어난다는 뜻이다.

분포란, 범위 안에서 특정 값을 가질 가능성을 말하며 이산확률분포와 역속확률분포가 될 수 있다.

  • 이산확률분포는 확률 변수가 가질 수 있는 값의 개수가 유한하다. 이산확률분포에서 가능한 값의 확률을 모두 더하면 항상 1이 된다. 대표적인 이산확률분포의 예는 주사위를 던진 결과를 나타내는 확률 변수이다.
  • 연속확률분포는 범위 안에서 특정 값을 가지는 연속 변수의 확률을 표현한다. 연속 변수는 범위 안에서 어떤 값이든 될 수 있으며 대표적으로 하루 중에 주어진 시간의 온도가 변화하는 것을 연속 변수라 할 수 있다.

엔트로피는 데이터 관점에서 엔트로피는 정보를 표현하는 효율성을 측정한다. 즉, 데이터의 무질서 정도를 말한다. 파일을 무손실로 압축하는 것은 엔트로피를 증가시킨다. 파일을 ZIP 압축 파일로 압축한다면 파일 크기는 크게 줄어들지 않는다. 이는 원본 데이터가 매우 높은 엔트로피를 갖고 있기 때문이다. 다른 말로는 매우 랜덤하기 때문이라고 할 수 있다. 따라서 효율적으로 표현하기가 어렵다. 영어 텍스트는 엔트로피가 매우 낮은데, 이는 텍스트가 그렇게까지 랜덤하지 않기 때문이다. 파일의 내용이 랜덤하지 않을 수록 데이터의 엔트로피도 낮아지고, 압축의 가능성도 커진다. 랜덤 숫자 생성의 관점에서 보면 엔트로피는 비트열의 랜덤성을 측정하는 것이다. 최대 엔트로피는 각 비트가 1과 0으로 완전한 랜덤 순차열이 되는 것이다. 완전한 랜덤 순차열의 정보 콘텐츠는 정보를 더 짧은 순차열로 표현 할 수 없으므로 엔트로피가 최대치가 된다. 최소 엔트로피는 순차열을 완벽하게 예측할 수 있다. 즉, 랜덤 숫자를 생성할 때는 순차열의 엔트로피가 최대치가 되는 것이 바람직하다.


랜덤 숫자 구하기

STL 은 랜덤 숫자 생성 관점에서 네 가지 용어를 사용한다.

  1. ‘랜덤 숫자 엔진’은 랜덤 비트열로 된 비부호 정수열을 생성하는 메커니즘을 정의한 클래스 템플릿이다. STL은 랜덤 숫자 엔진을 세 가지 클래스 템플릿으로 정의했다. 뒤에서 간단히 설명하겠지만, 여기에 사용된 알고리즘을 더 깊이 이해하는 게 아니라면 랜덤 숫자 엔진을 직접 사용하지 않는 게 좋다. 대신 랜덤 숫자 생성기를 사용하는 게 좋다.
  2. ‘랜덤 숫자 생성기’는 랜덤 숫자 엔진 클래스 템플릿을 미리 정의해 둔 인스턴스다. 각 생성기는 랜덤 숫자 엔진 클래스 템플릿에 특정 템플릿 인수를 적용한 것이다. 즉, 타입 별칭이다. STL은 랜덤 숫자 생성에서 잘 알려진 알고리즘을 구현한 랜덤 숫자 생성기를 몇 가지 미리 정의해두었다.
  3. ‘랜덤 숫자 엔진 어댑터’는 다른 랜덤 숫자 엔진으로 생성한 순차열을 수정해서 랜덤 숫자열을 생성하는 클래스 템플릿이다.
  4. ‘분포’는 랜덤 순차열의 숫자들이 범위 안에서 나타날 확률을 결정한다. STL은 매우 다양한 분포를 함수 객체로 정의한 클래스 템플릿을 제공한다.

랜덤 숫자 생성을 위한 알고리즘은 항상 하나 이상의 시드로 시작한다. 시드는 랜덤 숫자를 생성하는 계산에 사용할 초기 입력 값이다. 시드는 랜덤 숫자 생성기의 초기 상태를 결정하고, 전체 순차열을 결정한다. 랜덤 숫자 생성기의 알고리즘은 재귀적 구조로 되어 있다. 값을 생성하면 상태를 변경하게 되고, 변경된 상태는 다음 값을 생성하는 데 사용되는 식으로 이어진다. 따라서 랜덤 숫자 생성기는 주어진 시드나 시드들에 대해 항상 같은 순차열을 생성하게 된다. 따라서 시드가 랜덤 값이되는 것이 이상적이다. STL 에서 모든 랜덤 숫자 생성 알고리즘은 단일 시드로 초기화된다. 초기상태를 정의하는 데 더 많은 시드가 필요하다면 시드가 자동으로 생성된다. 따라서 랜덤 숫자열의 엔트로피는 시드에 따라 달라진다.

랜덤 시드를 구하기 위해서는 random_device 클래스를 이용하면 된다. random_device 클래스는 시드로 사용할 수 있는 랜덤 비부호 정숫값을 생성하는 함수 객체를 정의한다. 이 클래스는 랜덤 값을 위해 비결정적인 소스를 사용해야 하는데, 보통은 이 값을 운영체제에서 제공한다. 비결정적인 소스는 연속적인 키보드 키 누름 사이의 시간이나 마우스 클릭 사이의 간격, 현재 시간, 또는 물리적 특성을 측정한 것을 쓸 수 있다. radom_device 객체의 생성자는 매개변수로 string& 타입을 갖는다. 이 매개변수를 생략하면 사용하는 환경에 따라 기본 random_device 객체를 갖게 된다. 아래 코드를 보자. 8번씩 두 번 실행한 출력 값이 완전히 다르다는 것을 알 수 있다. random_device 클래스는 세 가지 함수 멤버만 정의하고 있다. min(), max() 멤버는 출력에서 가능한 값의 최솟값과 최댓값을 반환한다. entropy() 멤버는 소스의 엔트로피를 평가한 값을 double 타입으로 반환한다. 또는 구현체가 비결정적인 소스가 아닌 랜덤 넘버 엔진을 사용한다면 0을 반환한다. 아래는 랜덤 시드를 구하는 코드이다.

이러한 랜덤 시드를 이용해서 랜덤 숫자를 생성하여, 다양한 분포를 구할 수 있다.




Reply