C ++ 11은로 많은 새로운 옵션을 제공 random
합니다. 이 주제에 대한 표준 논문 은 C ++ 11의 난수 생성 N3551입니다.
사용 rand()
이 왜 문제가 될 수 있는지 알아 보려면 GoingNative 2013 행사 에서 제공된 Stephan T. Lavavej 의 rand () 고려 된 유해 프레젠테이션 자료를 참조하십시오 . 슬라이드는 주석에 있지만 여기에 직접 링크가 있습니다.
레거시 코드는 여전히 지원이 필요할 수 있으므로 boost
사용뿐만 아니라 다루고 rand
있습니다.
아래 예제는 cppreference 사이트에서 추출한 std :: mersenne_twister_engine 엔진 및 std :: uniform_real_distribution 을 사용하여 [0,10)
간격 에 따라 숫자를 생성 하고 다른 엔진 및 분배는 주석 처리됩니다 ( 실제 참조 ).
#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <random>
int main()
{
std::random_device rd;
//
// Engines
//
std::mt19937 e2(rd());
//std::knuth_b e2(rd());
//std::default_random_engine e2(rd()) ;
//
// Distribtuions
//
std::uniform_real_distribution<> dist(0, 10);
//std::normal_distribution<> dist(2, 2);
//std::student_t_distribution<> dist(5);
//std::poisson_distribution<> dist(2);
//std::extreme_value_distribution<> dist(0,2);
std::map<int, int> hist;
for (int n = 0; n < 10000; ++n) {
++hist[std::floor(dist(e2))];
}
for (auto p : hist) {
std::cout << std::fixed << std::setprecision(1) << std::setw(2)
<< p.first << ' ' << std::string(p.second/200, '*') << '\n';
}
}
출력은 다음과 유사합니다.
0 ****
1 ****
2 ****
3 ****
4 *****
5 ****
6 *****
7 ****
8 *****
9 ****
우리가 가기로 결정하면 출력 그래서, 어떤 당신이 선택하는 분포에 따라 달라집니다 표준 : normal_distribution 의 값이 2
모두 평균 과 STDDEV 예를 들어, dist(2, 2)
대신 출력이 유사하다 ( 이 살고 참조 )
-6
-5
-4
-3
-2 **
-1 ****
0 *******
1 *********
2 *********
3 *******
4 ****
5 **
6
7
8
9
다음은 제시된 일부 코드의 수정 된 버전입니다 N3551
( 실제 참조 ).
#include <algorithm>
#include <array>
#include <iostream>
#include <random>
std::default_random_engine & global_urng( )
{
static std::default_random_engine u{};
return u ;
}
void randomize( )
{
static std::random_device rd{};
global_urng().seed( rd() );
}
int main( )
{
// Manufacture a deck of cards:
using card = int;
std::array<card,52> deck{};
std::iota(deck.begin(), deck.end(), 0);
randomize( ) ;
std::shuffle(deck.begin(), deck.end(), global_urng());
// Display each card in the shuffled deck:
auto suit = []( card c ) { return "SHDC"[c / 13]; };
auto rank = []( card c ) { return "AKQJT98765432"[c % 13]; };
for( card c : deck )
std::cout << ' ' << rank(c) << suit(c);
std::cout << std::endl;
}
결과는 다음과 유사합니다.
5H 5S AS 9S 4D 6H TH 6D KH 2S QS 9H 8H 3D KC TD 7H 2D KS 3C TC 7D 4C QH QC QD JD AH JC AC KD 9D 5C 2H 4H 9C 8C JH 5D 4S 7C AD 3S 8S TS 2C 8D 3H 6C JS 7S 6S
후원
물론 Boost.Random 은 항상 옵션입니다. 여기서 boost :: random :: uniform_real_distribution을 사용하고 있습니다 .
#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_real_distribution.hpp>
int main()
{
boost::random::mt19937 gen;
boost::random::uniform_real_distribution<> dist(0, 10);
std::map<int, int> hist;
for (int n = 0; n < 10000; ++n) {
++hist[std::floor(dist(gen))];
}
for (auto p : hist) {
std::cout << std::fixed << std::setprecision(1) << std::setw(2)
<< p.first << ' ' << std::string(p.second/200, '*') << '\n';
}
}
랜드()
사용해야하는 경우 부동 소수점 난수를 생성하는 방법 에 대한 지침 rand()
은 C FAQ 를 참조하십시오 . 기본적으로 간격을 생성하기 위해 이와 유사한 예제를 제공합니다 [0,1)
.
#include <stdlib.h>
double randZeroToOne()
{
return rand() / (RAND_MAX + 1.);
}
다음 범위에서 임의의 숫자를 생성합니다 [M,N)
.
double randMToN(double M, double N)
{
return M + (rand() / ( RAND_MAX / (N-M) ) ) ;
}