JavaScript で乱数を扱う際の話です。

「乱数」はその名前の通り「事前に予測できないランダムな値」のことや、その生成の仕組みのことを呼びます。JavaScript にも乱数を生成する機能は標準で用意されており、Math.random() という関数を実行することで 0 から 1 の間のランダムな小数を取得することができます。

もし0から1の間の小数の乱数ではなく、「10以上20未満のランダムな整数の乱数」が必要な場合は以下のように Math.floor() (小数部分を切り捨てて整数化する関数)と組み合わせることで目的の乱数を得ることができます:
Math.floor( Math.random() * 10 ) + 10

この JavaScript の乱数は標準機能として備わっていて、すぐに使えるという点では便利です。しかしシード(seed)に対応していない、という、場合によっては困る点があります。

シードは乱数を初期化する時に指定する値です。同じシードで初期化した乱数システムは同じ乱数を返すようになります。例えば1という値をシードに指定して乱数を初期化して3回乱数を発生させたとします(発生した値を a1, a2, a3 とします)。別の機会に同じ1をシードに指定して乱数を初期化してから3回乱数を発生させて、それらの値をそれぞれ b1, b2, b3 とします。この時、同じシードを指定してから実行しているので、a1 = b1, a2 = b2, a3 = b3 が成立します。a1 も a2 も a3 も乱数なので事前に予測することはできませんが、同じシードを指定して実行したのであれば b1, b2, b3 がそれぞれ a1, a2, a3 と同じ値が取得できることが事前に保障されます。このように再現性のある乱数を発生させる仕組みが必要になることがある※のですが、JavaScript の Math.random() はこのシードには対応していない、という問題があります。

※例えば「ウェブページ内に1日ごとにランダムな画像を表示する(同じ日にアクセスした場合は同じ画像が表示される)」という仕組みを作ろうとした場合、本当にランダムな関数を使って表示画像を選ぼうとすると、アクセスするたびに異なる画像が選ばれてしまうことになります。 一方、シードに対応した乱数であれば、例えば日付からタイムスタンプ値を取るなどして数値化し、その数値をシードに指定して乱数を1個取得すれば、その値は事前に予測はできませんが(同じシードで初期化しているので)同じ日に実行していれば同じ値になります。ということは同じ画像を選んで表示することができるようになる、というものです。

で、このような再現性のある乱数を JavaScript で実現するにはどうすればよいか? という問題です。答としては「自分で用意する」ことになります。例えば以下のような感じ(こちらの記事を参考にしています):

class Random {
  constructor(seed = 19681106) {
    this.x = 31415926535;
    this.y = 8979323846;
    this.z = 2643383279;
    this.w = seed;
  }
  
  // XorShift
  next() {
    let t;
 
    t = this.x ^ (this.x << 11);
    this.x = this.y; this.y = this.z; this.z = this.w;
    return this.w = (this.w ^ (this.w >>> 19)) ^ (t ^ (t >>> 8)); 
  }
  
  // min以上max以下の乱数を生成する
  nextInt(min, max) {
    const r = Math.abs(this.next());
    return min + (r % (max + 1 - min));
  }
}

上述のようなクラスを事前に定義しておきます(x, y, z の値は自由に変更してかまいません。ちなみに↑の例は円周率の最初の31桁を使っています)。その上で以下のように使います:
  //. 今日の日付
  var dt = new Date();
  var y = dt.getFullYear();
  var m = dt.getMonth() + 1;
  m = ( ( m < 10 ) ? '0' : '' ) + m;
  var d = dt.getDate();
  d = ( ( d < 10 ) ? '0' : '' ) + d;

  //. 今日の午前零時のタイムスタンプをシードとして取得
  dt = new Date( y + '-' + m + '-' + d + ' 00:00:00' );
  var seed = dt.getTime();

  //. 今日の午前零時のタイムスタンプをシードに関数を初期化
  var random = new Random( seed );

  //. 0以上100未満の乱数を発生させる
  var value = random.nextInt( 0, 100 );

(かなり無理やり感ありますが・・)このように JavaScript を記述すると日が変わるまでの間は同じシード値を使って初期化することになります。したがって最後の行で乱数を発生させていますが、ここで取得する乱数値は同じ日に実行する間は同じ結果になる、というものです。