お手軽 乱数実装【C++11】

こちらは[C++ Advent Calendar 2018 2日目の記事](https://qiita.com/advent-calendar/2018/cpp)です。

[1日目: C++ で async/await をする](https://qiita.com/tan-y/items/6033ab9e7298999bf214)
[3日目: C++ ライフをよりハッピーにするための 14の小ネタ](https://qiita.com/Nabetani/items/4129e9a694883b330a64)

#C++の乱数は"初見殺し"なので……

皆さん、C++の乱数ライブラリである**`<random>`**は使用していますか？
まさか **C** の**`srand`**や**`rand`**を使用している人はいませんよね……？

C++の扱いに手馴れている人にとっては、**`<random>`**ライブラリは手ごわい相手ではないでしょう。
しかし、初心者にとっては**難攻不落**ではないかと思います。

そこで、以下の便利ソースコードを使用すると
簡単に、そして楽に乱数ライブラリが扱えるようになります。

ちなみにrandomライブラリの説明は2年前にいなむ先生が記事を出しているのでそちらをご覧ください。
[C++の乱数ライブラリが使いにくい話](https://qiita.com/_EnumHack/items/25fc998873d1bc7d2276)

#便利ソースコード

```cpp:Random.hpp
#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`**よりも簡単に扱えます。

#使い方

##通常の乱数を生成

```cpp:Source1.cpp
#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()`**で乱数生成します。

#範囲指定(余りの範囲の一様分布乱数)

```cpp:Source2.cpp
#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で割った余りの範囲の一様分布乱数**を生成します。

#範囲指定

```cpp:Source3.cpp
#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の範囲の乱数**を生成します。

#確率

```cpp:Source4.cpp
#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;
}
```

```
はずれ
あたり！
あたり！
あたり！
あたり！
はずれ
あたり！
あたり！
はずれ
あたり！
```

乱数で確率を使用します。

#初期値指定

```cpp:Source5.cpp
#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.
[![CC0](https://mirrors.creativecommons.org/presskit/buttons/88x31/svg/cc-zero.svg "CC0")](http://creativecommons.org/publicdomain/zero/1.0/deed.ja)

ソースコードは自由に使用してください。