Javaに関する様々な情報をご紹介します。

Javaに関する様々な情報をご紹介します。
評価

0

Math.random()を使用して3分の1の確率

double r = Math.random();
if (r < 1.0d / 3.0d) {
 //処理1
} else if ( r < 2.0d / 3.0d) {
 //処理2
} else {
 //処理3
}

としたとき、処理1~3は等確率になりますか。
想像では処理1のみ0.00...~...001(最小値?)だけ確率が高く起きそうなのですが。

5

回答

7499

閲覧

5件の回答

評価

0

失礼しました。意図がわかってもらえれば問題ないと思いましたが念のため訂正しておくと、高くなりそうなのは処理3です。(0.6666666666666666~0.9999999999999999?)

javadocによると、Math.random()は

0.0 以上で、1.0 より小さい正の符号の付いた double 値を返します。

とのことなので等確率でない可能性はあると思います。
ですがdouble型は、
System.out.println(0.3333333333333333 * 3.0d);
では1.0を返したりとよくわからないルールで計算されているため、今回のような場合も特殊な処理で問題ない修正されているのかと想像したためです。

評価

10

そもそもMath.randomでは一様分布には遠いし周期も短い。イニ
シャライズはともかく、生成には別のライブラリを使う方がいい。

比較にDouble#compare()を使う癖を付けておく方が良いかもしれ
ないが、誤差の面では気にしても仕方が無い。所詮は浮動小数点
だ。

>よくわからないルールで計算されている
ここも分かるようにしておくといいんじゃないか。

評価

0

質問者です。回答ありがとうございます。

compareは使うに越したことはなさそうですね、今後はそうしたいと思います。

調べてみたのですが、java.util.Randomぐらいしか他のものが見つかりませんでした。javadoc的にはMath.randomも一様分布らしいのですが、もっと周期の長いライブラリがあるのでしたら、是非教えていただきたく思います。

評価

10

標準パッケージと、commons系の中身はみんな一緒。

例えば(int)(1000*Math.random())での0〜999の出現回数を数え
ると、100万回でも結構バラツキがあったように記憶してる。

良く引き合いに出されるのは、メルセンヌ・ツイスタという
やつ。
もちろん、これとて浮動小数点の擬似乱数なので、完全な1/3
にはなり得ない。どこまでの精度を求めるかだな。標準パッ
ケージのものでも、大概の場合には十分な乱数なんだし。

評価

0

(int)(1000 * Math.random())をInteger.MAX_VALUE回行い、回数の(max - min) / maxを計算してみたところ全て0.4~0.5%でした。
直感だけで言えば今回の話では問題なさそうだと思うのですが、このあたりはよくわかっていないので、追々きっちり検討していこうと思います。

メルセンヌ・ツイスタ法の存在についても知ることができましたので、必要があればこちらを使おうと思います。

これで解決ということで回答を締め切らせて貰おうと思います。ありがとうございました。

質問から6ヶ月以上経過しているので、回答を書き込むことはできません。