3

これは数学の質問のように見えるかもしれませんが、Javascript の疑似乱数ジェネレーターに排他的にリンクされているため、SO に適していると思います。そうでない場合は、自由に別の場所に移動してください。

まず、ES は疑似乱数ジェネレーターで使用されるアルゴリズムを指定していないことを認識してMath.random()いますが、範囲はおおよそ均一な分布を持つ必要があると指定しています。

15.8.2.14 ランダム ( )

実装依存のアルゴリズムまたは戦略を使用して、0以上 1 未満の正符号を持つ Number 値を返します。この関数は引数を取りません。

ここまでは順調ですね。今、私は最近MDNからのこのデータに出くわしました:

JavaScript の数値は IEEE 754 浮動小数点数であり、最も近い偶数に丸められるため、Math.random()それ自体の範囲を除いて、これらの範囲は正確ではなく、境界によっては非常にまれなケースで可能であることに注意してください ( 2^62の 1 のオーダー) を使用して、通常は除外される上限を計算します。

わかった。それは私をいくつかのテストに導きました、結果は(明らかに)ChromeコンソールとFirefoxのFirebugで同じです:

>> 0.99999999999999995
1
>> 0.999999999999999945
1
>> 0.999999999999999944
0.9999999999999999

私の質問をより明確にするために、簡単な実用的な例に入れましょう。

Math.floor(Math.random() * 1)

上記のコードを考慮すると、IEEE 754 浮動小数点数は最も近い偶数に丸められる動作をし、Math.random()範囲が均等に分散されているという評価の下で、通常は除外される上限 (1上記のコード)を返す確率は次のようになると結論付けました。である0.000000000000000055555...、それはおよそ1/18,000,000,000,000,000

MDN 番号を今見ると、 と1/2^62評価され1/4,611,686,018,427,387,904ます。つまり、私の計算結果よりも 200 倍以上小さくなっています。

私は間違った計算をしていますか?Firefox の疑似乱数ジェネレーターは、この 200 倍の差を生成するのに十分に均等に分散されていないのでしょうか?

私はこれを回避する方法を知っており、毎日の使用でそのような小さなオッズを考慮する必要さえないことを認識していますが、ここで何が起こっているのか、私の数学が壊れているのか、Mozilla のものなのかを理解したいと思っています (うまくいけば前者です)。=]どんな入力でも大歓迎です。

4

1 に答える 1

2

Math.random() の数値を 1 に丸める必要はありません。

現在のバージョンの IE、Chrome、および FF の実装 (取得している結果から推測) を調べていたところ、0 から 0.1111111111111111111111111111111111111111111111111 までの間隔の数値を常に取得する必要があることをほぼ確実に意味するいくつかの観察結果があります。 (これは0.999999999999999944.toString(2)、いくつかの小さい10進数でもあります)。

クロム:ここは簡単です。32 ビットの数値を生成し、それを 1 << 32 で割ることによって数値を生成します ((1 << 30) * 4 * Math.random()常に整数を返すことがわかります)。

FF:ここでは、数値は常に最大で 0.11... (53x 1) になるように生成され、実際には小数点以下 53 桁だけを使用しているようです。Math.random().toString(2).length - 2( 53 以上は返されないことがわかります)。

IE:ここでは FF に非常に似ていますが、小数点以下の最初の桁が 0 の場合は桁数が多くなり、確実に 1 に丸められない点が異なります。Math.random().toString(2).match(/1[01]*$/)[0].length( 53 以上は返されないことがわかります)。

私は (今は証拠を提供することはできませんが) どの実装も、説明されているグループのいずれかに該当し、1 に丸めることに問題はないと考えています。

于 2013-01-12T14:26:59.647 に答える