HOWTO · C++

C++에서 임의의 부동 소수점 수를 생성하는 방법

이 기사에서는 C++에서 임의의 부동 숫자를 생성하는 방법을 보여줍니다.

이 페이지의 내용

C++11의 <random> 라이브러리를 사용하면 원하는 범위의 부동 소수점 의사 난수를 생성할 수 있습니다. std::uniform_real_distribution에 하한과 상한을 지정하고, 난수 엔진이 값의 시퀀스를 제공합니다. 애플리케이션에 필요한 정밀도에 따라 float 또는 double을 사용하고, 레거시 코드를 유지보수하는 경우에만 rand를 사용하세요.

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

다음 완전한 프로그램은 반개구간 [10, 100)에서 값 5개를 생성합니다. 고정 시드를 사용하므로 같은 표준 라이브러리 구현에서는 엔진의 시퀀스를 재현할 수 있어 디버깅에 유용합니다. 분포 알고리즘은 구현 간에 동일한 시퀀스를 만들도록 규정되어 있지 않으므로 출력되는 값은 구현에 따라 달라질 수 있습니다.

다음 예제를 실행하세요:

#include <iomanip>
#include <iostream>
#include <random>

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

  for (int i = 0; i < 5; ++i) {
    std::cout << std::setprecision(10) << distribution(engine) << '\n';
  }
}
78.99481399
96.50696843
96.65823206
73.63312607
11.77415091

분포의 템플릿 인수로 결과 형식을 선택합니다. 기본값은 double이며, 표준에서 지원하는 형식은 float, double, long double입니다. 호출 지점에서 형식을 명확히 알 수 있도록 하나를 지정하세요. 예제는 double을 사용하며, std::uniform_real_distribution<float>를 지정하면 float 값이 생성됩니다. 경계값은 실수이며 분포에서 상한은 포함되지 않습니다. 상한을 포함하면 다음 구간과 경계값이 겹칠 수 있는 범위를 조정할 때 이 반개구간이 유용합니다. 예를 들어 0.0부터 1.0까지의 범위는 정규화된 비율을 나타내고, 10.0부터 100.0까지의 범위는 선택한 단위의 측정값을 나타낼 수 있습니다.

정밀도가 충분하고 저장 공간이나 대역폭이 중요하다면 float을 사용하고, 일반적인 정밀도와 범위의 균형이 필요하다면 double을 선택하세요. 추가 정밀도가 필요할 때는 long double을 사용할 수 있지만, 실제로 늘어나는 정밀도는 구현에 따라 다릅니다. 특히 템플릿 인수를 바꿀 때는 가능한 한 경계값의 형식도 분포 형식과 맞추면 의도한 범위를 쉽게 확인할 수 있습니다. 엔진 시드가 고정되어 있어도 서로 다른 표준 라이브러리 구현에서 같은 출력 시퀀스가 나온다고 보장되지는 않습니다.

시퀀스를 생성할 때는 엔진을 유지하고 재사용하세요. 값마다 새 엔진을 만들고 다시 시드하면 시퀀스가 반복되거나 품질이 저하될 수 있습니다. 재현 가능한 결과가 필요하면 위 예제처럼 고정값으로 시드하세요. 실행할 때마다 다른 시퀀스가 필요하다면, 구현이 비결정적 출력을 지원하는 경우 std::random_device에서 시드 재료를 얻을 수 있습니다. 모든 시스템에서 그런 동작이 보장되는 것은 아닙니다. 어느 방법을 사용하더라도 이 범용 의사 난수 생성기는 보안에 민감한 값에 적합하지 않습니다. 시드는 엔진을 한 번 초기화하는 값이지, 값을 뽑을 때마다 새 엔진을 만들라는 뜻이 아닙니다. 실행 간 결과를 재현해야 하는 애플리케이션이라면 다른 입력값과 함께 시드도 기록하세요. 보안 토큰이 필요하다면 이 분포와 엔진 대신 암호학적 난수원을 사용하세요.

rand를 제한적인 레거시 대안으로 사용하기

C 라이브러리의 rand()는 0부터 구현에 따라 달라지는 RAND_MAX까지의 의사 난수 정수를 양 끝값을 포함해 반환합니다. 이를 부동 소수점 범위로 변환하려면 크기를 조정하기 전에 부동 소수점 연산으로 RAND_MAX를 나누세요. 다음 예제는 [10, 100] 범위로 변환하며, rand()가 RAND_MAX를 반환하면 상한도 포함됩니다:

#include <cstdlib>
#include <iostream>

int main() {
  const double lower = 10.0;
  const double upper = 100.0;
  std::srand(2026);

  for (int i = 0; i < 5; ++i) {
    const double value = lower + (upper - lower) *
        (static_cast<double>(std::rand()) / RAND_MAX);
    std::cout << value << '\n';
  }
}
60.2772
88.4741
67.8989
11.5099
83.7273

rand()는 상태와 통계적 품질에 한계가 있습니다. 고정 시드는 같은 C 라이브러리 구현에서 이 예제를 재현 가능하게 만들지만, 예측 불가능하거나 안전하게 만들지는 않습니다. 새 C++ 코드에는 엔진과 분포를 분리하고 결과 형식과 범위를 직접 선택할 수 있는 <random>을 우선 사용하세요.