ミニからマックスのランダム整数
重要度: 2
randomInteger(min, max)
関数を作成します。これは、可能な値としてmin
とmax
を両方含む、min
からmax
へのランダムな整数数を生成します。
min..max
の間の数値はすべて同じ確率で表示される必要があります。
動作の例
alert( randomInteger(1, 5) ); // 1
alert( randomInteger(1, 5) ); // 3
alert( randomInteger(1, 5) ); // 5
前のタスクの解決策をベースとして使用できます。
単純だが間違った解決策
最も単純だが間違った解決策は、min
からmax
までの数値を生成し、切り捨てることです
function randomInteger(min, max) {
let rand = min + Math.random() * (max - min);
return Math.round(rand);
}
alert( randomInteger(1, 3) );
関数は機能しますが、正しくありません。エッジ値min
とmax
を取得する確率は、他の値よりも2倍低くなります。
上記の例を何度も実行すると、2
が最も頻繁に表示されることがわかります。
これは、Math.round()
が間隔1..3
からランダムな数値を取得し、次のように切り捨てるためです
values from 1 ... to 1.4999999999 become 1
values from 1.5 ... to 2.4999999999 become 2
values from 2.5 ... to 2.9999999999 become 3
ここで、1
は2
よりも2倍少ない値を取得することが明確にわかります。3
でも同じです。
正しい解決策
タスクには多くの正しい解決策があります。その1つは、インターバルの境界線を調整することです。同じインターバルを確保するには、0.5
から3.5
の値を生成し、必要な確率をエッジに追加することができます
function randomInteger(min, max) {
// now rand is from (min-0.5) to (max+0.5)
let rand = min - 0.5 + Math.random() * (max - min + 1);
return Math.round(rand);
}
alert( randomInteger(1, 3) );
別の方法は、min
からmax+1
までのランダム数値にMath.floor
を使用することです
function randomInteger(min, max) {
// here rand is from min to (max+1)
let rand = min + Math.random() * (max + 1 - min);
return Math.floor(rand);
}
alert( randomInteger(1, 3) );
すべての範囲がこの方法でマッピングされました。
values from 1 ... to 1.9999999999 become 1
values from 2 ... to 2.9999999999 become 2
values from 3 ... to 3.9999999999 become 3
すべての範囲の長さは同じであり、最終的な分布が均一になります。