Namespaces
Variants

Pseudo-random number generation

From cppreference.net

난수 라이브러리는 무작위 및 의사 무작위 숫자를 생성하는 클래스를 제공합니다. 이러한 클래스에는 다음이 포함됩니다:

  • 균일 난수 비트 생성기(URBG)는 균일 분포를 가진 정수 시퀀스를 생성하는 의사 난수 생성기인 난수 엔진과 (사용 가능한 경우) 진난수 생성기를 모두 포함합니다.
  • 난수 분포 (예: uniform , normal , 또는 poisson distributions )는 URBG의 출력을 다양한 통계적 분포로 변환합니다.

URBG와 분포는 함께 사용되어 난수 값을 생성하도록 설계되었습니다. 모든 난수 엔진은 특정 시드 값으로 초기화되고, 직렬화 및 역직렬화되어 반복 가능한 시뮬레이터와 함께 사용될 수 있습니다.

목차

균일 무작위 비트 생성기

균일 난수 비트 생성기 는 가능한 결과 범위 내의 각 값이 (이상적으로) 동일한 확률로 반환되는 부호 없는 정수 값을 반환하는 함수 객체입니다.

모든 균일 난수 비트 생성기는 UniformRandomBitGenerator 요구 사항을 충족합니다. C++20은 또한 uniform_random_bit_generator 개념을 정의합니다.

헤더 파일에 정의됨 <random>
타입이 균일 난수 비트 생성자로 적합함을 명시
(concept)

난수 엔진

랜덤 넘버 엔진 (일반적으로 엔진 으로 줄여씀)은 시드 데이터를 엔트로피 소스로 사용하여 의사 난수를 생성하는 균일 난수 비트 생성기입니다.

언제든지, 타입 E 의 엔진 e 는 음수가 아닌 정수 i 에 대한 상태 e i 를 가집니다. 생성 시, e 는 엔진 매개변수와 초기 시드(또는 시드 시퀀스)에 의해 결정되는 초기 상태 e 0 를 가집니다.

다음 속성들은 모든 엔진 유형 E 에 대해 항상 정의됩니다:

  • E 의 상태 크기를 E::result_type 의 크기 배수로 나타낸 값(즉, ( sizeof e i ) / sizeof ( E :: result_type ) ).
  • e 의 상태 e i 를 후속 상태 e i+1 로 전이시키는 전이 알고리즘 TA (즉, TA ( e i ) == e i+1 ).
  • e 의 상태를 E::result_type 타입의 값으로 매핑하는 생성 알고리즘 GA , 그 결과는 의사 난수입니다.

의사 난수 시퀀스는 TA GA 를 번갈아 호출하여 생성할 수 있습니다.

표준 라이브러리는 세 가지 다른 종류의 의사 난수 생성 알고리즘 구현을 클래스 템플릿으로 제공하므로 알고리즘을 사용자 정의할 수 있습니다. 어떤 엔진을 사용할지 선택하는 것은 여러 가지 절충점을 수반합니다:

  • 선형 합동 엔진 은 비교적 빠르며 상태 저장을 위한 요구 공간이 매우 작습니다.
  • 메르센 트위스터 엔진 은 더 느리고 상태 저장 요구 사항이 더 크지만, 적절한 매개변수를 사용할 경우 가장 긴 비반복 시퀀스와 가장 바람직한 스펙트럼 특성(바람직함의 정의에 따라)을 가집니다.
  • 캐리 감산 엔진 은 고급 산술 명령어 세트가 없는 프로세서에서도 매우 빠르게 동작하지만, 더 큰 상태 저장 공간과 때로는 덜 바람직한 스펙트럼 특성을 가지는 단점이 있습니다.
  • Philox 엔진 카운터 기반 난수 생성기 입니다. 작은 상태 크기와 긴 주기(최소 2^130 이상)를 가지며, 대규모 병렬 난수 생성이 필요한 몬테카를로 시뮬레이션에 사용하기 위해 설계되었습니다. 쉽게 벡터화 및 병렬화가 가능하며 GPU 최적화 라이브러리에서 구현됩니다.
(C++26부터)

이들 난수 엔진 중 그 어느 것도 암호학적으로 안전하지 않습니다. 모든 보안 작업과 마찬가지로, 해당 목적을 위해서는 암호화 라이브러리를 사용해야 합니다 (예: OpenSSL RAND_bytes ).

이 템플릿들로부터 인스턴스화된 모든 타입은 RandomNumberEngine 요구 사항을 충족합니다.

헤더 파일에 정의됨 <random>
선형 합동 알고리즘을 구현함
(클래스 템플릿)
메르센 트위스터 알고리즘을 구현함
(클래스 템플릿)
캐리 감산( 지연 피보나치 ) 알고리즘을 구현함
(클래스 템플릿)
카운터 기반 병렬화 가능 생성기
(클래스 템플릿)

난수 엔진 어댑터

랜덤 넘버 엔진 어댑터는 다른 랜덤 넘버 엔진을 엔트로피 소스로 사용하여 의사 난수를 생성합니다. 일반적으로 기본 엔진의 스펙트럼 특성을 변경하는 데 사용됩니다.

헤더 파일에 정의됨 <random>
난수 엔진의 일부 출력을 버림
(클래스 템플릿)
난수 엔진의 출력을 지정된 비트 수의 블록으로 패킹
(클래스 템플릿)
난수 엔진의 출력을 다른 순서로 전달
(클래스 템플릿)

미리 정의된 난수 생성기

여러 구체적인 인기 알고리즘이 미리 정의되어 있습니다.

헤더에 정의됨 <random>
유형 정의
minstd_rand0 (C++11) std:: linear_congruential_engine < std:: uint_fast32_t ,
16807 , 0 , 2147483647 >

1969년 Lewis, Goodman 및 Miller가 발견하고, 1988년 Park과 Miller에 의해 "최소 표준"으로 채택됨

minstd_rand (C++11)

std:: linear_congruential_engine < std:: uint_fast32_t ,
48271 , 0 , 2147483647 >
1993년 Park, Miller, Stockmeyer가 권장한 새로운 "최소 표준"

mt19937 (C++11)

std:: mersenne_twister_engine < std:: uint_fast32_t ,
32 , 624 , 397 , 31 ,
0x9908b0df , 11 ,
0xffffffff , 7 ,
0x9d2c5680 , 15 ,
0xefc60000 , 18 , 1812433253 >
Matsumoto와 Nishimura의 32비트 메르센 트위스터, 1998

mt19937_64 (C++11)

std:: mersenne_twister_engine < std:: uint_fast64_t ,
64 , 312 , 156 , 31 ,
0xb5026f5aa96619e9 , 29 ,
0x5555555555555555 , 17 ,
0x71d67fffeda60000 , 37 ,
0xfff7eee000000000 , 43 ,
6364136223846793005 >
마츠모토와 니시무라의 64비트 메르센 트위스터, 2000

ranlux24_base (C++11) std:: subtract_with_carry_engine < std:: uint_fast32_t , 24 , 10 , 24 >
ranlux48_base (C++11) std:: subtract_with_carry_engine < std:: uint_fast64_t , 48 , 5 , 12 >
ranlux24 (C++11) std:: discard_block_engine < std:: ranlux24_base , 223 , 23 >

24비트 RANLUX 생성기 (Martin Lüscher와 Fred James, 1994)

ranlux48 (C++11) std:: discard_block_engine < std:: ranlux48_base , 389 , 11 >

48비트 RANLUX 생성기 (Martin Lüscher와 Fred James, 1994)

knuth_b (C++11) std:: shuffle_order_engine < std:: minstd_rand0 , 256 >
philox4x32 (C++26) std:: philox_engine < std:: uint_fast32_t , 32 , 4 , 10 ,
0xCD9E8D57 , 0x9E3779B9 ,
0xD2511F53 , 0xBB67AE85 >
philox4x64 (C++26) std:: philox_engine < std:: uint_fast64_t , 64 , 4 , 10 ,
0xCA5A826395121157 , 0x9E3779B97F4A7C15 ,
0xD2E7470EE14C6C93 , 0xBB67AE8584CAA73B >
default_random_engine (C++11) 구현 정의 RandomNumberEngine 타입

비결정적 난수

std::random_device 는 비결정적 균일 난수 비트 생성기입니다. 하지만 비결정적 난수 생성에 대한 지원이 없는 경우 구현체가 std::random_device 를 의사 난수 엔진을 사용하여 구현하는 것이 허용됩니다.

하드웨어 엔트로피 소스를 사용하는 비결정적 난수 생성기
(클래스)

난수 분포

난수 분포는 URBG의 출력을 사후 처리하여 결과 출력이 정의된 통계적 확률 밀도 함수에 따라 분포되도록 합니다.

난수 분포는 RandomNumberDistribution 요구 사항을 충족합니다.

헤더에 정의됨 <random>
균일 분포
범위 내에서 균일하게 분포된 정수 값을 생성합니다
(클래스 템플릿)
범위 내에서 균일하게 분포된 실수 값을 생성합니다
(클래스 템플릿)
베르누이 분포
bool 값을 베르누이 분포 기반으로 생성합니다
(클래스)
이항 분포 상의 정수 값을 생성합니다
(클래스 템플릿)
음이항 분포를 따르는 정수 값을 생성합니다 negative binomial distribution
(클래스 템플릿)
기하 분포 상의 정수 값을 생성합니다
(클래스 템플릿)
포아송 분포
푸아송 분포 상의 정수 값을 생성합니다
(클래스 템플릿)
지수 분포 상의 실수 값을 생성합니다
(클래스 템플릿)
감마 분포 상의 실수 값을 생성합니다
(클래스 템플릿)
Weibull distribution 에 따른 실수 값을 생성합니다
(클래스 템플릿)
극값 분포 상의 실수 값을 생성합니다
(클래스 템플릿)
정규 분포
표준 정규 (가우시안) 분포 에서 실수 값을 생성합니다
(클래스 템플릿)
로그 정규 분포 상의 실수 값을 생성합니다
(클래스 템플릿)
카이제곱 분포 상의 실수 값을 생성합니다
(클래스 템플릿)
코시 분포 상의 실수 값을 생성합니다
(클래스 템플릿)
Fisher의 F-분포 상의 실수 값을 생성합니다
(클래스 템플릿)
실수 값을 스튜던트 t-분포 에 따라 생성함
(클래스 템플릿)
표본 분포
이산 분포에서 정수 값을 생성함
(클래스 템플릿)
일정한 부분 구간에 분포된 실수 값을 생성합니다
(클래스 템플릿)
정의된 부분 구간에 분포된 실수 값을 생성합니다
(클래스 템플릿)

유틸리티

헤더 파일에 정의됨 <random>
주어진 정밀도의 실수 값을 [ 0 , 1 ) 구간에 균일하게 분포시킴
(함수 템플릿)
(C++11)
범용 편향 제거 스크램블 시드 시퀀스 생성기
(클래스)

난수 알고리즘

헤더 파일에 정의됨 <random>
범위를 균일 난수 비트 생성기로부터 생성된 난수로 채움
(알고리즘 함수 객체)

C 랜덤 라이브러리

위에서 설명한 엔진과 분포 외에도, C 랜덤 라이브러리의 함수와 상수들도 사용 가능하지만 권장하지 않습니다:

헤더 파일에 정의됨 <cstdlib>
의사 난수 생성
(함수)
의사 난수 생성기 시드 설정
(함수)
std::rand 가 생성할 수 있는 최댓값
(매크로 상수)

예제

#include <cmath>
#include <iomanip>
#include <iostream>
#include <map>
#include <random>
#include <string>
int main()
{
    // 실제 랜덤 값으로 시드 설정 (사용 가능한 경우)
    std::random_device r;
    // 1과 6 사이의 랜덤 평균값 선택
    std::default_random_engine e1(r());
    std::uniform_int_distribution<int> uniform_dist(1, 6);
    int mean = uniform_dist(e1);
    std::cout << "무작위로 선택된 평균: " << mean << '\n';
    // 해당 평균을 중심으로 정규 분포 생성
    std::seed_seq seed2{r(), r(), r(), r(), r(), r(), r(), r()};
    std::mt19937 e2(seed2);
    std::normal_distribution<> normal_dist(mean, 2);
    std::map<int, int> hist;
    for (int n = 0; n != 10000; ++n)
        ++hist[std::round(normal_dist(e2))];
    std::cout << "정규 분포 (평균 " << mean << "):\n"
              << std::fixed << std::setprecision(1);
    for (auto [x, y] : hist)
        std::cout << std::setw(2) << x << ' ' << std::string(y / 200, '*') << '\n';
}

가능한 출력:

무작위로 선택된 평균: 4
정규 분포 (평균 4):
-4
-3
-2
-1
 0 *
 1 ***
 2 ******
 3 ********
 4 *********
 5 ********
 6 ******
 7 ***
 8 *
 9
10
11
12

참고 항목

C 문서 for 의사 난수 생성