[解決済み】乱数生成器を使うとモジュロバイアスがかかると言われるのはなぜ?
疑問点
この質問はよく見かけますが、本当の意味での具体的な回答は見たことがありません。そこで、以下のような乱数生成器を使用したときに、なぜ "モジュロ・バイアス" が発生するのかを理解する助けになればと思い、ここに投稿しようと思います。
rand()
をC++で作成しました。
どのように解決するのですか?
そこで
rand()
は擬似乱数生成器で、0から
RAND_MAX
で定義される定数です。
cstdlib
(この
記事
に関する一般的な概要については
rand()
).
では、例えば0と2の間の乱数を生成したい場合はどうなるでしょうか。説明の便宜上、次のようにしましょう。
RAND_MAX
が 10 で、0 から 2 までの乱数を生成するために
rand()%3
. しかし
rand()%3
は、0と2の間の数字を同じ確率で生成するわけではありません!
いつ
rand()
は0、3、6、9を返します。
rand()%3 == 0
. したがって、P(0) = 4/11
いつ
rand()
は1、4、7、10を返す。
rand()%3 == 1
. したがって、P(1) = 4/11
いつ
rand()
は2,5,8を返す。
rand()%3 == 2
. したがって、P(2) =
3/11
これでは、0と2の間の数字が同じ確率で生成されません。もちろん、小さな範囲ではこれは大きな問題ではないかもしれませんが、大きな範囲では分布が歪み、小さな数字に偏りが生じる可能性があります。
では、どのような場合に
rand()%n
は、0からn-1までの数値の範囲を同じ確率で返すのでしょうか?それは
RAND_MAX%n == n - 1
. この場合、先ほどの仮定と合わせて
rand()
は0から
RAND_MAX
のモジュロクラスも等しい確率で分布しているはずです。
では、この問題を解決するにはどうしたらよいのでしょうか。乱数を発生させ続け、目的の範囲に入る数を得るというのが粗い方法です。
int x;
do {
x = rand();
} while (x >= n);
の値が小さいと効率が悪くなります。
n
を持っているだけなので
n/RAND_MAX
を実行する必要があります。
RAND_MAX/n
を呼び出します。
rand()
を平均すると
で割り切れる長さの大きな範囲を指定するのが、より効率的な計算式のアプローチとなります。
n
というように
RAND_MAX - RAND_MAX % n
で、その範囲に入る乱数が出るまで乱数を発生させ続けて、そのモジュラスを取る。
int x;
do {
x = rand();
} while (x >= (RAND_MAX - RAND_MAX % n));
x %= n;
の値が小さい場合
n
を1回以上呼び出す必要はほとんどありません。
rand()
.
引用文献と参考文献。
関連
-
[解決済み】 != と =! の違いと例(C++の場合)
-
[解決済み】C++でランダムな2倍数を生成する
-
[解決済み】「Expected '(' for function-style cast or type construction」エラーの意味とは?
-
[解決済み] 変数サイズのオブジェクトが初期化されないことがある c++
-
[解決済み] C++11では、標準化されたメモリモデルが導入されました。その意味するところは?そして、C++プログラミングにどのような影響を与えるのでしょうか?
-
[解決済み] ランダムな文字列を使用するこのコードは、なぜ "hello world" と表示されるのですか?
-
[解決済み] Javascriptで乱数発生器の種を蒔く
-
[解決済み】画像処理。コカ・コーラ缶」認識のためのアルゴリズム改良
-
[解決済み] Intel CPU の _mm_popcnt_u64 で、32 ビットのループカウンターを 64 ビットに置き換えると、パフォーマンスが著しく低下します。
-
[解決済み】乱数発生器が1つの乱数しか発生させない。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Visual C++で "Debug Assertion failed "の原因となる行を見つける。
-
[解決済み】Visual Studio 2013および2015でC++コンパイラーエラーC2280「削除された関数を参照しようとした」が発生する
-
[解決済み】#include<iostream>は存在するのですが、「識別子 "cout "は未定義です」というエラーが出ます。なぜですか?
-
[解決済み】C++の余分な資格エラー
-
[解決済み】標準ライブラリにstd::endlに相当するタブはあるか?
-
[解決済み] Objective-Cで乱数を発生させる
-
[解決済み] Swiftで乱数を生成する方法とは?
-
[解決済み] ランダムでユニークな英数字の文字列を生成するには?
-
[解決済み] 配列からランダムに要素を選ぶ
-
[解決済み] NSMutableArrayをシャッフルする最も良い方法は何ですか?