[C++] 260 乱数生成方法 randomヘッダ

[M1 Mac, Monterey 12.6.3, clang 13.0.0, SDL 2.26.2, ChatGPT Plus, NO IDE]

テトリスC++版ではMacOSのstdlib.hにあるrand関数をこれまで使っていましたが、偏りがひどく乱数生成器として用を成さないため、ChatGPTに教えてもらった<random>ヘッダに変更しました。

#include <random>

int TetroTypeGenerator()
{	
	int tetroType;

	if (GeneratorCount == 0){
		arr = {0, 1, 2, 3, 4, 5, 6};
	}

	while(1){
		// 乱数生成器を初期化する
		std::random_device seed_gen;
		std::mt19937 engine(seed_gen());
		
		// 0から6の7つの整数から一つランダムに選択する
		std::uniform_int_distribution<int> dist(0, 6);
		int tetroType = dist(engine);
		// tetroType = rand() % kNumTetrominoTypes; // 偏りがひどいので不採用
		cout << "tetroType生成器: " << tetroType << endl;

		if (arr.size() == 0){
			arr = {0, 1, 2, 3, 4, 5, 6};
			cout << "テトロミノ配列が空になったのでリセットしました" << endl;
		} else if (arr.size() == 1){
			tetroType = arr.front();
			arr = {};

			cout << "tetroType残り1: " << to_string(tetroType) << endl;
			GetScoreAndDate();
			makeRanking();
			GeneratorCount++;
			return tetroType;
		}

		for (auto it = arr.begin(); it != arr.end(); ) {
			if (*it == tetroType) {
				it = arr.erase(it);

				cout << "tetroType: " << to_string(tetroType) << endl;
				GetScoreAndDate();
				makeRanking();

				GeneratorCount++;
				return tetroType;

			} else {
				it++;
			}
		}
	}
}

ChatGPT
Q: MacOSのstdlib.hにあるrand関数の生成する乱数が偏っています。なぜですか?

MacOSのstdlib.hにあるrand関数は、線形合同法に基づいた乱数生成アルゴリズムを使用しています。このアルゴリズムは、周期が短く、生成される乱数の分布が均等ではないため、偏った乱数が生成される可能性があります。

具体的には、rand関数は0からRAND_MAXまでの範囲の整数を生成しますが、生成される乱数の分布が均等でないため、特定の値がより頻繁に生成される傾向があります。また、線形合同法による乱数生成アルゴリズムは、初期値に依存するため、同じ初期値を使用する場合は、同じ乱数の系列が生成されます。

そのため、rand関数が生成する乱数は、科学的なシミュレーションや暗号学的な目的などのように、高品質な乱数が必要な場合には適していません。代わりに、乱数生成器として、より高品質なアルゴリズムを使用することが推奨されます。たとえば、C++11以降では、<random>ヘッダーに、様々な種類の乱数生成器が用意されています。