6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

DelphiAdvent Calendar 2024

Day 11

[Delphi][小ネタ] XorShift

Last updated at Posted at 2024-12-10

はじめに

9日に引き続き乱数の話です。
今回はアルゴリズムの話で、XorShift についてです。

XorShift とは

Wikipedia によると

Xorshiftは疑似乱数列生成法の1つである。
George Marsagliaが2003年に提案した。
演算が排他的論理和とビットシフトのみであるため高速であるなどの特徴がある。

とのことで、メルセンヌ・ツイスタとかより非常に高速なのに、周期もそこそこ長くて使い勝手が良い乱数生成法です。

実装

Delphi での実装はこんな感じ

function XorShift: UInt32;
begin
  // FA は初期化されている必要がある
  FA := FA xor (FA shl 13);
  FA := FA xor (FA shr 17);
  FA := FA xor (FA shl 5);
  Result := FA;
end;

今回、これも Unit 化しました。

Unit 化

unit PK.Math.XorShift;

interface

implementation

uses
  System.SysUtils;

type
  TXorShift = record
  private class var
    FA: UInt32;
  private
    class procedure Init; static;
  public
    class procedure SetSeed(ANewSeed: UInt64); static;
    class function Execute: UInt32; static;
  end;

{ TXorShift }

class function TXorShift.Execute: UInt32;
begin
  FA := FA xor (FA shl 13);
  FA := FA xor (FA shr 17);
  FA := FA xor (FA shl 5);
  Result := FA;
end;

class procedure TXorShift.Init;
begin
  FA := Round(Frac(Now) * 24 * 60 * 60 * 1000) mod 1000;;
  Random32Proc := Execute;
  RandomizeProc := SetSeed;
end;

class procedure TXorShift.SetSeed(ANewSeed: UInt64);
begin
  DefaultRandomize(ANewSeed);
  FA := RandSeed;
end;

initialization
  TXorShift.Init;

end.

ここで新たな RandomizeProc 変数が出てきました。
これは Randomize 関数を呼んだ時に、こちらで指定した関数が呼ばれるようにする物です。
XorShift は初期化が必要なので、これを使って初期化できます。
Randomize を呼ぶと、時刻を元にした値がやってきます。

ここでは、それを DefaultRandomize 関数に渡して、初期化を代行させています。
DefaultRandomize では RandSeed 変数にシード値を入れてくれるため、それを使って FA メンバ変数を初期化しています。

サンプル

前回と同じサンプルを動かしてみました。

結果はこうなりました。

0 949
1 1036
2 973
3 1047
4 1006
5 1024
6 991
7 989
8 987
9 999

まとめ

XorShift は性能と高速さを併せ持っているので通常の乱数を使う場面であれば、ほぼ万能と言えます。
暗号論的強度はない(次の数字が予測可能である)ため、その用途には CNG Random が向いています。

ちなみにシード値を指定できるタイプの乱数生成では、同じシード値からは必ず同じ乱数列が生成されます。
その性質のため、ゲーム等で役に立ちます。
たとえば、ぷよぷよで2人プレイの場合、2人に同じぷよが降ってくる必要がありますが、同じシード値を持った乱数生成関数があれば、容易に実現できるのです。

6
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?