HOWTO · C++

C++에서 0과 1 사이의 난수를 생성하는 방법

이 문서에서는 0과 1 간격 C++ 사이의 난수를 만드는 방법을 보여줍니다.

이 페이지의 내용

0 이상 1 미만의 부동소수점 의사 난수를 생성하려면 C++11 난수 엔진과 std::uniform_real_distribution<double>을 함께 사용합니다. 예제는 고정된 시드를 사용하므로, 같은 구현에서 같은 엔진과 시드를 사용하면 동일한 수열을 다시 얻을 수 있습니다. 새 C++ 코드에는 <random>을 사용하고, 기존 코드를 유지보수할 때는 std::rand를 사용하세요.

C++11 <random>으로 부동소수점 난수 생성하기

<random>을 포함하고 난수 엔진을 만든 다음, 값이 필요할 때마다 엔진을 분포 객체에 전달합니다. 엔진은 의사 난수 비트열을 생성하고, 분포 객체는 그 비트를 요청한 형식과 범위의 값으로 변환합니다. 이 완전한 예제는 값 다섯 개를 출력합니다. 고정된 시드를 사용하므로 같은 표준 라이브러리 구현에서 다시 실행하면 같은 결과를 얻을 수 있습니다.

#include <iostream>
#include <random>

int main() {
    std::mt19937 engine(2026);
    std::uniform_real_distribution<double> distribution(0.0, 1.0);

    for (int i = 0; i < 5; ++i) {
        std::cout << distribution(engine) << '\n';
    }
}

출력되는 숫자는 표준 라이브러리 구현에 따라 달라집니다. 같은 구현에서는 같은 엔진과 시드를 사용하면 같은 수열이 시작됩니다. 다른 수열을 원한다면 다른 시드를 사용하거나, std::random_device로 엔진을 한 번 초기화하세요. 다만 모든 시스템에서 이 장치가 비결정적 엔트로피를 제공하는 것은 아닙니다.

출력 범위와 엔진 선택 이해하기

std::uniform_real_distribution<double>(0.0, 1.0)이 지정하는 구간은 반열린 구간입니다. 0은 반환될 수 있지만 1은 제외됩니다. 템플릿 인수는 부동소수점 결과 형식(float, double, long double)을 선택합니다. 분포 객체에는 엔진 인수가 필요하므로, 분포 객체만으로는 난수를 생성할 수 없습니다.

엔진은 의사 난수 수열을 결정하고 시드는 그 수열의 시작 위치를 결정합니다. std::mt19937은 알고리즘이 명시된 표준 엔진으로 널리 사용됩니다. 특정 엔진이 중요하지 않을 때는 std::default_random_engine이 편리하지만, 어떤 엔진을 선택할지는 구현에 따라 달라집니다. 따라서 서로 다른 표준 라이브러리에서도 같은 수열을 얻어야 한다면 적합성이 떨어집니다. 엔진은 한 번 시드하고 재사용하세요. 값을 생성할 때마다 다시 시드하면 값이 반복될 수 있고 수열의 품질도 나빠집니다. 이 기능들은 시뮬레이션, 게임, 일반적인 무작위 동작에는 적합하지만 암호화 비밀값에는 적합하지 않습니다.

기존 코드를 위한 경우에만 std::rand 사용하기

오래된 코드에서는 <cstdlib>에 선언된 std::rand를 사용할 수 있습니다. 이 함수는 0부터 RAND_MAX까지의 정수를 반환하며, 양 끝값을 모두 포함합니다. 정수 나눗셈을 피하려면 나누기 전에 부동소수점 형식으로 변환하세요. 예를 들어 static_cast<double>(std::rand()) / (static_cast<double>(RAND_MAX) + 1.0)이라는 인라인 식은 정수를 원하는 범위로 변환합니다.

이 방식은 std::rand가 RAND_MAX를 반환하더라도 결과가 1보다 작게 유지되도록 합니다. 실행마다 다른 값을 원한다면 값을 생성하기 전에 std::srand를 한 번 호출하세요. 흔히 시간 기반 시드를 사용하지만, 여러 번 실행해도 같은 시드가 사용될 수 있으며 시딩만으로 생성기의 품질이 개선되지는 않습니다. RAND_MAX는 구현에 따라 달라지고, std::rand는 <random>보다 엔진과 수열을 제어하기 어렵습니다. 새 코드에는 C++11 엔진과 분포를 사용하고, 기존 인터페이스가 요구하는 경우에만 이 레거시 함수를 사용하세요.