16番会議室「玉石混淆みんなで作るSample蔵」に寄せられたサンプル
"高速で高品位な乱数生成ユニット(D3版)"
この発言は #01200 ひの さんの高速で高品位な乱数生成ユニット に対するコメントです
この発言に対し以下のコメントが寄せられています
#01205 ひの さん RE:高速で高品位な乱数生成ユニット(D3版)
#1200のソースは Delphi 4 以降用でした。今度は Delphi 3 用です。
変更点はCardinalをLongintにしたことと、最後の出力のところで0.50を加
える処理をしたことです。この結果、オリジナルの乱数列と比べて、0..0.5
と 0.5..1.0 の値が入れ代わる関係になります。しかし乱数列であることには
代わりはないので実用上問題ないと思います。
100000000回の呼び出しにかかる時間でベンチマークすると。
Empty Loop: 5540ms <-代入だけの空ループ
MTRandom : 14440ms <-Mersenne Twister
Random : 18255ms <-標準のRandom
Random/MTRandom : 1.428651685
空ループの時間を差し引くと標準のRandom関数に比べて約1.4倍高速です。
(*-----------------------------------------------------------------
Delphi 3 unit for Mersenne Twister random number generator
Original source :
http://www.math.keio.ac.jp/~nisimura/random/int/mt19937int.c
Mersenne Twister Home Page :
http://www.math.keio.ac.jp/~matumoto/mt.html
Ported to Free Pascal unit by M. Hinoue (2000/11/27)
Ported to Delphi 3 unit by M. Hinoue (2000/11/28)
------------------------------------------------------------------*)
unit MTRand;
(* A C-program for MT19937: Integer version (1999/10/28) *)
(* genrand() generates one pseudorandom unsigned integer (32bit) *)
(* which is uniformly distributed among 0 to 2^32-1 for each *)
(* call. sgenrand(seed) sets initial values to the working area *)
(* of 624 words. Before genrand(), sgenrand(seed) must be *)
(* called once. (seed is any 32-bit integer.) *)
(* Coded by Takuji Nishimura, considering the suggestions by *)
(* Topher Cooper and Marc Rieffel in July-Aug. 1997. *)
(* This library is free software; you can redistribute it and/or *)
(* modify it under the terms of the GNU Library General Public *)
(* License as published by the Free Software Foundation; either *)
(* version 2 of the License, or (at your option) any later *)
(* version. *)
(* This library is distributed in the hope that it will be useful, *)
(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)
(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *)
(* See the GNU Library General Public License for more details. *)
(* You should have received a copy of the GNU Library General *)
(* Public License along with this library; if not, write to the *)
(* Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA *)
(* 02111-1307 USA *)
(* Copyright (C) 1997, 1999 Makoto Matsumoto and Takuji Nishimura. *)
(* When you use this, send an email to: matumoto@math.keio.ac.jp *)
(* with an appropriate reference to your work. *)
(* REFERENCE *)
(* M. Matsumoto and T. Nishimura, *)
(* "Mersenne Twister: A 623-Dimensionally Equidistributed Uniform *)
(* Pseudo-Random Number Generator", *)
(* ACM Transactions on Modeling and Computer Simulation, *)
(* Vol. 8, No. 1, January 1998, pp 3--30. *)
(*------------*)
Interface
(*------------*)
(* initialize *)
procedure MTRandomSeed(Seed : Longint);
(* return real random number *)
function MTRandom : extended;
(* return integer random number [0..N-1] *)
function MTRandomInt(N : Longint) : Longint;
(*----------------*)
Implementation
(*----------------*)
const
(* Period parameters *)
N = 624;
M = 397;
MATRIX_A = $9908b0df; (* constant vector a *)
UPPER_MASK = $80000000; (* most significant w-r bits *)
LOWER_MASK = $7fffffff; (* least significant r bits *)
(* Tempering parameters *)
TEMPERING_MASK_B = $9d2c5680;
TEMPERING_MASK_C = $efc60000;
var
mti : integer;
mt : array[0..N-1] of Longint; (* the array for the state vector *)
(*---------------------------------------
initialize the array with a seed
-----------------------------------------*)
procedure MTRandomSeed(seed : Longint);
var
i : integer;
begin
for i := 0 to N - 1 do begin
mt[i] := seed and $ffff0000;
seed := 69069 * seed + 1;
mt[i] := mt[i] or ((seed and $ffff0000) shr 16);
seed := 69069 * seed + 1;
end;
mti := N;
end;
(*---------------------------------
return real random number [0..1)
-----------------------------------*)
function MTRandom : extended;
const
mag01 : array[0..1] of Longint = ($0, MATRIX_A);
(* mag01[x] = x * MATRIX_A for x=0,1 *)
var
y : Longint;
kk : integer;
begin
if mti >= N then begin (* generate N words at one time *)
for kk := 0 to N-M-1 do begin
y := (mt[kk] and UPPER_MASK) or (mt[kk+1] and LOWER_MASK);
mt[kk] := mt[kk+M] xor (y shr 1) xor mag01[y and $1];
end;
for kk := N - M to N-2 do begin
y := (mt[kk] and UPPER_MASK) or (mt[kk+1] and LOWER_MASK);
mt[kk] := mt[kk+(M-N)] xor (y shr 1) xor mag01[y and $1];
end;
y := (mt[N-1] and UPPER_MASK) or (mt[0] and LOWER_MASK);
mt[N-1] := mt[M-1] xor (y shr 1) xor mag01[y and $1];
mti := 0;
end;{if}
y := mt[mti];
Inc(mti);
y := y xor (y shr 11);
y := y xor ((y shl 7) and TEMPERING_MASK_B);
y := y xor ((y shl 15) and TEMPERING_MASK_C);
MTRandom := (y xor (y shr 18)) * 2.3283064365386962891e-10 + 0.500;
end; (* adjustment for Delphi 3 ^^^^^^^*)
(*---------------------------------------
return integer random number [0..N-1]
-----------------------------------------*)
function MTRandomInt(N : Longint) : Longint;
begin
MTRandomInt := Trunc(N * MTRandom);
end;
(*-------------------
initialize unit
---------------------*)
begin
MTRandomSeed(4357);
end.
2000/11/28(Tue) 08:35pm GFD03044 ひの
- FDELPHI MES(16):玉石混淆みんなで作るSample蔵【見本蓄積】 00/12/02 -
Original document by ひの 氏 ID:(GFD03044)
ここにあるドキュメントは NIFTY SERVEの Delphi Users' Forum の16番会議室「玉石混淆みんなで作るSample蔵」に投稿されたサンプルです。これらのサンプルはボーランド株式会社がサポートする公式のものではありません。また、必ずしも動作が検証されているものではありません。これらのサンプルを使用したことに起因するいかなる損害も投稿者、およびフォーラムスタッフはその責めを負いません。使用者のリスクの範疇でご使用下さい。
Copyright 1996-2002 Delphi Users' Forum
|