어두운 배경이 싫으시다면 페이지 우측 하단에 보이는 초승달 모양의 아이콘을 클릭하면 화이트모드로 변경됩니다. 초승달 모양 버튼 : `화이트/다크 모드` 전환 |
1. rand() 함수 : 난수 생성
기존의 C 스타일의 rand() 함수는 `<cstdlib>` 헤더에서 제공하고 있는 난수 함수입니다. C++ 에서는 `<iostream>` 안에 기본적으로 포함되기 때문에 해당 라이브러리를 추가하면 사용 가능합니다.
rand() 함수로 난수를 발생하게 되면 `0 ~ RAND_MAX` 라는 범위 안에서 난수가 생성됩니다. 이때 `RAND_MAX`는 상수로 32,767로 정의되어 있습니다. 그래서 최종적으로 발생되는 난수는 `0 ~ 32,767` 이라고 보면 됩니다.
rand() 함수는 가장 기본적인 형태의 의사난수(pseudo-random number) 발생 함수이기 때문에 간단한 작업에 사용하기에는 적합하지만, 난수 품질이나 보안성이 낮아서 복잡한 난수 발생이나 멀티스레드 등에서 사용하기에는 적합하지 않습니다.
rand() 함수는 난수를 발생할 때 시드값(seed)을 사용하는데, 같은 시드값이라면 항상 같은 결과를 반환합니다. 그래서 다양한 결과를 얻고 싶다면 srand() 함수를 이용하여 시드를 초기화해야 합니다. 보통은 현재 시간을 시드로 사용합니다.
🔹난수 생성 코드 예제
#include <iostream>
using namespace std;
int main()
{
srand((unsigned int)time(NULL)); // 난수 seed 초기화
for (int i = 0; i < 10; ++i) {
cout << rand() << endl; // 0 ~ 32,767 범위에서 랜덤 난수 생성
}
return 0;
}
2. rand() 사용법
🟦 최소, 최대 범위 지정해서 생성하기
특정한 범위의 값으로 난수를 발생하고 싶다면 나머지 연산자 `%`를 사용하여 최대값 범위로 연산하면 됩니다. 다만 난수로 생성되는 최대값의 범위는 지정한 값보다 1이 작은 값이 생성됩니다.
ex) `rand() % 50` => 0 ~ 49 범위에서 난수 발생
최솟값을 지정하고 싶다면 단순히 더해주면 됩니다.
ex) `(rand() % 50) + 1` => 1 ~ 50 범위에서 난수 발생
만약 최소, 최대값을 직접 지정하여 그 범위 안에서 난수를 발생시키려면 아래와 같이 공식을 이용하면 됩니다. 주로 게임에서 최소, 최대 데미지 사이의 데미지를 발생시킨다면 아래와 같이 사용하시면 됩니다.
`rand() % (max - min + 1) + min`
ex) 50 ~ 100 난수 발생 = `rand() % (100 - 50 + 1) + 50`
=> 마지막 50 더하기 전에 나온 결과는 0 ~ 50이고, 여기에 50을 더하면 50 ~ 100의 난수를 생성
🟦 난수 생성 범위 제한
rand() 함수로 생성할 수 있는 난수의 범위는 `RAND_MAX`, 즉 32,767까지 생성할 수 있습니다. 물론 rand() 함수를 사용하더라도 약간의 편법으로 확장은 할 수 있지만 품질이 좋지 않고 오류가 많아 추천하지 않는 방법입니다.
그래도 혹시 다른 곳에서 정보를 얻고 사용할 수 있기 때문에 사용을 방지하기 위해 일단 아래에 공식을 적어놓겠습니다. 이런 방식을 사용하기 보다는 아래에서 따로 설명하는 `random` 라이브러리를 사용하는 것이 난수 품질 및 보안, 균등한 난수 분포를 지원하므로 추천합니다.
`(int)(((double)rand() / ((double)RAND_MAX + 1.0)) * 40000)`
위와 같이 사용하면 `double` 실수형으로 rand() 함수로 생성된 난수를 `RAND_MAX + 1`의 값으로 나누어 정규화를 거치면 `[0, 1)`, 즉 0부터 1미만의 값이 랜덤하게 생성됩니다. 이 값을 원하는 범위의 숫자를 곱하면 일단 `RAND_MAX` 값보다는 큰 수를 생성할 수는 있지만, 값이 커지면 커질수록 오류율이 커집니다.
`(double)rand() / (double)RAND_MAX + 1.0`에서 최대값으로 `32,767 / 32,768 = 0.99996948···` 값이 나오므로, 이 값에 곱하면 소수점 이하의 값으로 인해 최대값의 오차가 발생합니다.
ex) 0.99996948 * 40,000 = 39,998.xxx
`RAND_MAX`이하의 값으로 난수를 발생하는 것은 위의 rand() 함수를 이용하는 것만으로도 충분합니다. 다만, 큰 값의 난수를 생성하려면 기존의 C스타일 방식으로는 한계가 있으므로 아래의 `random` 라이브러리를 사용하는 것을 추천합니다.
3. C++ random 라이브러리로 난수 생성
C++11 이후에는 더 나은 난수 생성기를 제공하는 `random` 헤더가 도입되어 품질이 우수하고 다양한 난수 분포를 지원합니다. 아래는 사용 코드 예시입니다.
#include <iostream>
#include <random>
int main() {
std::random_device rd; // 하드웨어 기반 랜덤 엔진 (seed 생성용)
std::mt19937 gen(rd()); // Mersenne Twister 엔진
std::uniform_int_distribution<> dis(1, 100); // 1~100 범위의 균등 분포
for (int i = 0; i < 10; ++i) {
std::cout << dis(gen) << std::endl; // 난수 출력
}
return 0;
}
`mt19937` 같은 엔진을 통해서 균일하면서도 예측 불가능한 난수를 생성합니다. 또한 `uniform_int_distribution`으로 균등 분포 방식 또는 `normal_distribution` 정규 분포 등 다양한 분포 방식을 제공합니다.
구독 및 좋아요는 컨텐츠를 생산하는데 많은 도움이 됩니다. 😊
감사합니다.