こちらはC++ Advent Calendar 2018 2日目の記事です。
1日目: C++ で async/await をする
3日目: C++ ライフをよりハッピーにするための 14の小ネタ
#C++の乱数は"初見殺し"なので……
皆さん、C++の乱数ライブラリである**<random>
は使用していますか?
まさか C のsrand
やrand
**を使用している人はいませんよね……?
C++の扱いに手馴れている人にとっては、<random>
ライブラリは手ごわい相手ではないでしょう。
しかし、初心者にとっては難攻不落ではないかと思います。
そこで、以下の便利ソースコードを使用すると
簡単に、そして楽に乱数ライブラリが扱えるようになります。
ちなみにrandomライブラリの説明は2年前にいなむ先生が記事を出しているのでそちらをご覧ください。
C++の乱数ライブラリが使いにくい話
#便利ソースコード
#pragma once
#include <random>
#include <cstdint>
class Rand {
private:
//32ビット版メルセンヌ・ツイスタ
std::mt19937 mt;
//非決定論的な乱数
std::random_device rd;
public:
//コンストラクタ(初期化)
Rand() { mt.seed(rd()); }
//初期値
void seed() {
mt.seed(rd());
}
void seed(const std::uint_fast32_t seed_) {
mt.seed(seed_);
}
//通常の乱数
std::uint_fast32_t operator()() {
return mt();
}
//0~最大値-1 (余りの範囲の一様分布乱数)
std::int_fast32_t operator()(const std::int_fast32_t max_) {
std::uniform_int_distribution<> uid(0, ((max_ > 0) ? (std::int_fast32_t)max_ - 1 : 0));
return uid(mt);
}
//最小値~最大値
std::int_fast32_t operator()(const std::int_fast32_t min_, const std::int_fast32_t max_) {
std::uniform_int_distribution<> uid((min_ <= max_) ? min_ : max_, (min_ <= max_) ? max_ : min_);
return uid(mt);
}
//確率
bool randBool(const double probability_) {
std::bernoulli_distribution uid(probability_);
return uid(mt);
}
bool randBool() {
std::uniform_int_distribution<> uid(0, 1);
return ((uid(mt)) ? true : false);
}
};
static thread_local Rand rnd;
C++の**<random>
**ライブラリを初心者でも
扱いやすくしたクラスです。
C言語の**rand
**よりも簡単に扱えます。
#使い方
##通常の乱数を生成
#include "Random.hpp"
#include <iostream>
int main() {
for (size_t i = 0; i < 10; ++i) {
std::cout << rnd() << std::endl;
}
return 0;
}
1177009351
53076842
3741984662
4148031424
3743658273
3492815540
3731663521
2691610594
1148602447
3200622187
**rnd()
**で乱数生成します。
#範囲指定(余りの範囲の一様分布乱数)
#include "Random.hpp"
#include <iostream>
int main() {
for (size_t i = 0; i < 10; ++i) {
std::cout << rnd(10) << std::endl;
}
return 0;
}
0
1
3
9
5
7
1
5
5
7
rnd(n)
で通常乱数をnで割った余りの範囲の一様分布乱数を生成します。
#範囲指定
#include "Random.hpp"
#include <iostream>
int main() {
for (size_t i = 0; i < 10; ++i) {
std::cout << rnd(10, 20) << std::endl;
}
return 0;
}
10
19
18
10
19
14
20
11
13
13
rnd(n1 , n2)
でn1からn2の範囲の乱数を生成します。
#確率
#include "Random.hpp"
#include <iostream>
int main() {
for (size_t i = 0; i < 10; ++i) {
std::cout << (rnd.randBool(0.7) ? "あたり!" : "はずれ") << std::endl;
}
return 0;
}
はずれ
あたり!
あたり!
あたり!
あたり!
はずれ
あたり!
あたり!
はずれ
あたり!
乱数で確率を使用します。
#初期値指定
#include "Random.hpp"
#include <iostream>
int main() {
for (size_t i = 0; i < 10; ++i) {
rnd.seed(1000);
std::cout << rnd() << std::endl;
}
return 0;
}
2807145907
2807145907
2807145907
2807145907
2807145907
2807145907
2807145907
2807145907
2807145907
2807145907
**rnd.seed(n)
で初期値が指定できます。
ちなみにrnd.seed()
**と値を入れない場合は、
ランダムな値を初期値として設定します。
##ソースコードのライセンス
These codes are licensed under CC0.
ソースコードは自由に使用してください。