レッスンに戻る

ミニからマックスのランダム整数

重要度: 2

randomInteger(min, max)関数を作成します。これは、可能な値としてminmaxを両方含む、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) );

関数は機能しますが、正しくありません。エッジ値minmaxを取得する確率は、他の値よりも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

ここで、12よりも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

すべての範囲の長さは同じであり、最終的な分布が均一になります。