C ++ 11에서 난수 생성 : 생성 방법, 작동 원리 [닫은] 하는 데 도움이 필요하면

나는 최근에 C ++ 11에서 난수를 생성하는 새로운 방법을 발견했지만 그것에 대해 읽은 논문 을 소화 할 수 없었 습니다 ( 엔진 , 분포 와 같은 수학 용어 , “모든 정수가 똑같이 생성 될 가능성이있는 곳 “).

누구든지 설명해 주시겠습니까

  • 그들은 무엇인가?
  • 무슨 뜻입니까?
  • 생성하는 방법?
  • 어떻게 작동합니까?
  • 기타

난수 생성에 대한 하나의 FAQ에서 모든 것을 호출 할 수 있습니다.



답변

질문은 완전한 답변을하기에는 너무 광범위하지만 몇 가지 흥미로운 점을 선택하겠습니다.

“동일한 가능성이있는”이유

동일한 확률로 숫자 0, 1, …, 10을 생성하는 간단한 난수 생성기가 있다고 가정합니다 (이를 고전적인 것으로 생각하십시오 rand()). 이제 각각 동일한 확률을 가진 0, 1, 2 범위의 난수를 원합니다. 무릎을 꿇는 반응은 rand() % 3. 그러나 잠깐, 나머지 0과 1이 나머지 2보다 더 자주 발생하므로 이것은 올바르지 않습니다!

이것이 우리가 예에서 와 같이 균일 한 임의 정수의 소스를 가져와 원하는 분포로 바꾸는 적절한 분포 가 필요한 이유 Uniform[0,2]입니다. 이것을 좋은 도서관에 맡기는 것이 가장 좋습니다!

엔진

따라서 모든 무작위성의 중심에는 특정 간격에 걸쳐 균일하게 분포하고 이상적으로는 매우 긴 기간을 갖는 일련의 숫자를 생성하는 우수한 의사 난수 생성기가 있습니다. 의 표준 구현은 rand()종종 최고가 아니므로 선택하는 것이 좋습니다. Linear-congruential과 Mersenne twister는 두 가지 좋은 선택입니다 (LG는 실제로에서도 자주 사용됩니다 rand()). 다시 말하지만, 라이브러리가 처리하도록하는 것이 좋습니다.

작동 원리

쉬움 : 먼저 엔진을 설치하고 시드하십시오. 시드는 “무작위”숫자의 전체 시퀀스를 완전히 결정하므로 a /dev/urandom) 매번 다른 번호 (예 :에서 가져옴)를 사용 하고 b) 무작위 선택 시퀀스를 다시 생성하려는 경우 시드를 저장합니다.

#include <random>

typedef std::mt19937 MyRNG;  // the Mersenne Twister with a popular choice of parameters
uint32_t seed_val;           // populate somehow

MyRNG rng;                   // e.g. keep one global instance (per thread)

void initialize()
{
  rng.seed(seed_val);
}

이제 배포판을 만들 수 있습니다.

std::uniform_int_distribution<uint32_t> uint_dist;         // by default range [0, MAX]
std::uniform_int_distribution<uint32_t> uint_dist10(0,10); // range [0,10]
std::normal_distribution<double> normal_dist(mean, stddeviation);  // N(mean, stddeviation)

… 엔진을 사용하여 난수를 만드세요!

while (true)
{
  std::cout << uint_dist(rng) << " "
            << uint_dist10(rng) << " "
            << normal_dist(rng) << std::endl;

}

동시성

<random>기존 방식 보다 선호하는 또 하나의 중요한 이유 rand()는 난수 생성 스레드를 안전하게 만드는 방법이 이제 매우 명확하고 분명하다는 것입니다. 스레드 로컬 시드에 시드 된 자체 스레드 로컬 엔진을 각 스레드에 제공하거나 액세스를 동기화합니다. 엔진 개체에.

기타

  • codeguru에서 무작위로 TR1에 대한 흥미로운 기사 .
  • Wikipedia 에는 좋은 요약이 있습니다 (감사합니다, @Justin).
  • 원칙적으로 각 엔진은 result_type시드에 사용할 올바른 통합 유형 인 typedef a 를 사용해야합니다. 나는에 대한 씨앗을 강제로 저를 강요 한 번 버그 구현했다 생각 std::mt19937uint32_t64에를, 결국이 고정되어야하며, 당신이 말할 수 MyRNG::result_type seed_val있어 매우 쉽게 교체 엔진을합니다.

답변

난수 생성기는 숫자가 주어지면 새로운 숫자를 제공하는 방정식입니다. 일반적으로 첫 번째 숫자를 제공하거나 시스템 시간과 같은 항목에서 가져온 숫자를 제공합니다.

새 번호를 요청할 때마다 이전 번호를 사용하여 방정식을 실행합니다.

난수 생성기는 다른 숫자보다 동일한 숫자를 더 자주 생성하는 경향이있는 경우 그다지 좋은 것으로 간주되지 않습니다. 즉, 1과 5 사이의 임의의 숫자를 원하고 다음과 같은 숫자 분포가있는 경우 :

  • 1 : 1 %
  • 2 : 80 %
  • 3 : 5 %
  • 4 : 5 %
  • 5 : 9 %

2는 다른 숫자보다 더 자주 생성되므로 다른 숫자보다 생성 될 가능성이 높습니다. 모든 숫자가 똑같다면 매번 각 숫자를 얻을 확률이 20 %입니다. 달리 말하면 위의 분포는 2가 선호되기 때문에 매우 고르지 않습니다. 모두 20 %의 분포는 균등합니다.

일반적으로 진정한 난수를 원한다면 난수 생성기보다는 날씨 또는 다른 자연 소스와 같은 것에서 데이터를 가져옵니다.


답변