C ++ 11 memberi Anda banyak opsi baru random
. Makalah kanonik pada topik ini adalah N3551, Random Number Generation dalam C ++ 11
Untuk melihat mengapa menggunakan rand()
bisa menjadi masalah, lihat rand () Dianggap bahan presentasi Berbahaya oleh Stephan T. Lavavej yang diberikan selama acara GoingNative 2013 . Slide ada di komentar tetapi di sini ada tautan langsung .
Saya juga membahas boost
dan menggunakan rand
karena kode lawas mungkin masih memerlukan dukungannya.
Contoh di bawah ini disaring dari situs cppreference dan menggunakan mesin std :: mersenne_twister_engine dan std :: uniform_real_distribution yang menghasilkan angka dalam [0,10)
interval, dengan mesin dan distribusi lain dikomentari ( lihat langsung ):
#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';
}
}
output akan mirip dengan yang berikut:
0 ****
1 ****
2 ****
3 ****
4 *****
5 ****
6 *****
7 ****
8 *****
9 ****
Output akan bervariasi tergantung pada distribusi yang Anda pilih, jadi jika kami memutuskan untuk pergi dengan std :: normal_distribution dengan nilai 2
untuk mean dan stddev misalnya dist(2, 2)
outputnya akan mirip dengan ini ( lihat langsung ):
-6
-5
-4
-3
-2 **
-1 ****
0 *******
1 *********
2 *********
3 *******
4 ****
5 **
6
7
8
9
Berikut ini adalah versi modifikasi dari beberapa kode yang disajikan dalam N3551
( lihat langsung ):
#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;
}
Hasil akan terlihat mirip dengan:
5H 5 S SEBAGAI 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
Dorongan
Tentu saja Boost.Random selalu menjadi pilihan juga, di sini saya menggunakan 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 ()
Jika Anda harus menggunakan rand()
maka kita bisa pergi ke FAQ C untuk panduan tentang Bagaimana saya bisa menghasilkan angka acak floating-point? , yang pada dasarnya memberikan contoh yang mirip dengan ini untuk menghasilkan suatu interval [0,1)
:
#include <stdlib.h>
double randZeroToOne()
{
return rand() / (RAND_MAX + 1.);
}
dan untuk menghasilkan angka acak dalam kisaran dari [M,N)
:
double randMToN(double M, double N)
{
return M + (rand() / ( RAND_MAX / (N-M) ) ) ;
}