« MiGrep ver1.3を公開しました | トップページ | Lazarus1.8RC4とクロスコンパイル環境の構築 »

2017.09.09

Delphi/Lazarusでの正規分布乱数の発生

正規分布乱数を発生させるためにはどのような方法がベストなのかDelphiで試してみました。
比較したアルゴリズムはボックスミュラー法と中心極限法理による正規分布乱数生成にDelphi標準関数のRandGを加えた3種類で、生成元の一様乱数はDelphi標準のRandomとメルセンヌ・ツイスターアルゴリズムを用いたDelphi用MT19937ライブラリを用いて見ました。

テスト方法はそれぞれ任意の正規分布乱数をグラフに表示させての”見た感じ”比較と一応定量的な評価として±1σ,±2σ,±3σそれぞれの確立分布と実際の分布数を比較して、その差をパーセント表示させて誤差の大きさを見ることにしました。
とここまでは良かったのですが、何とDelphi 10.1/10.2 StarterエディションにはTeeChartが付属していないためグラグ表示が出来ないことが判明。仕方がないので、一度はDelphi XE2 Pro版でテストプログラムを作成したものの、Starterしか持ってないから確認出来ない!という方がいるかも知れないと思い、あらためてLazarusで作成し直しました(LazarusにはTAChartというTeeChartに似たコンポーネントがあります)。

で、その結果ですが・・・どれもあまり代わり映えがしないようで、生成数が10,000個になるとどれもほとんど差がありません。
まぁ、よほど正確性が必要な用途に用いるのではない限り、Delphi/Lazarus標準のRandGが最強ではないかと思った次第です。
#それにしてもTeeChartにしてもTAChartにしても、機能が豊富すぎて使うのがものすごく面倒くさいです。

参考にLazarusプロジェクトソースと実行ファイルをアップしておきます

// ボックスミュラー法による乱数生成
procedure TForm1.BoxMullerTransform(RandType: integer; var x, y: Double);
var
  r1, r2: double;
begin
  case RandType of
    TYPEMT19937:
      begin
        r1 := mt19937_double(mtctx);
        r2 := mt19937_double(mtctx);
      end;
    else begin
      r1 := Random;
      r2 := Random;
    end;
  end;
  x := Sqrt(-2.0 * Ln(r1)) * Cos(2.0 * Pi * r2);
  y := Sqrt(-2.0 * Ln(r1)) * Sin(2.0 * Pi * r2);
end;
 
// 中心極限定理による乱数生成
function TForm1.CentralLimitTheorem(RandType: integer): double;
var
  i: integer;
  r: double;
begin
  r := 0.0;
  for i := 1 to 12 do
    case RandType of
      TYPEMT19937:
        r := r + mt19937_double(mtctx);
      else
        r := r + Random;
    end;
  Result := r - 6.0;
end; 

Test

「RandTest.zip」をダウンロード

|

« MiGrep ver1.3を公開しました | トップページ | Lazarus1.8RC4とクロスコンパイル環境の構築 »

コメント

コメントを書く



(ウェブ上には掲載しません)




トラックバック


この記事へのトラックバック一覧です: Delphi/Lazarusでの正規分布乱数の発生:

« MiGrep ver1.3を公開しました | トップページ | Lazarus1.8RC4とクロスコンパイル環境の構築 »