ランダム数の周期 yoichiro 2007/06/08 00:13:53 ├現在のバージョンでは, 白石 和夫 2007/06/08 14:32:38 └十進BASICの組込み関数RNDにより発生する乱... 荒田浩二 2007/06/08 18:58:39 ├!何故か不明、ときどき一致しない時がある。... SECOND 2007/06/10 19:59:10 (修正1回) │├出張で返事おそくなりました。 yoichiro 2007/06/11 09:27:14 (修正1回) │└RANDOMIZE文がPCの内部時計を参照し種を与え... 荒田浩二 2007/06/12 15:45:57 (修正1回) │ ├補足 荒田浩二 2007/06/12 16:50:44 │ │└RANDOMIZEの実体は 白石 和夫 2007/06/12 17:32:44 (修正2回) │ │ └RANDOMIZEも種が、TIME関数と同一と、いうこ... SECOND 2007/06/12 18:00:26 (修正1回) │ │ └MyTimeは拡張精度なので,それが差がでる原... 白石 和夫 2007/06/12 18:16:23 │ │ └先生のリストで、同値のMytimeに挟まれるMy... SECOND 2007/06/12 22:06:23 (修正5回) │ │ └整数丸めコントロール・ワードが勝手にゆら... 白石 和夫 2007/06/13 07:23:02 (修正2回) │ │ └私のパソコンでも荒田氏と同様の時刻の規則... SECOND 2007/06/13 07:53:00 (修正2回) │ └DELETED SECOND 2007/06/12 17:23:39 (削除) └リストの中で、"田"が"川"になっていた事を... SECOND 2007/06/18 06:52:15
ランダム数の周期 yoichiro 2007/06/08 00:13:53 ツリーへ
ランダム数の周期 |
返事を書く ノートメニュー |
yoichiro <lrmllemwxh> 2007/06/08 00:13:53 | |
十進BASICでは、RNDを用いた時
「使用乱数の種類と周期」 は、どのようなものになるのでしょうか。 また、十進BASICを使用した旨を論文に載せる場合、 英語ではどのように表記すればよろしいでしょうか。 |
├現在のバージョンでは, 白石 和夫 2007/06/08 14:32:38 ツリーへ
Re: ランダム数の周期 |
返事を書く ノートメニュー |
白石 和夫 <fbdfvqwhki> 2007/06/08 14:32:38 | |
現在のバージョンでは,
function random:extended; begin result:=System.Random; end; のようにDelphiの乱数をそのまま利用しています。 以前のバージョンでは, function random:extended; const a=16807.0; m=2147483647.0; var temp:extended; begin temp:=a*seed; seed:=temp-m*int(temp/m); random:=seed/m end; で計算していました。 十進BASICでは,モジュールの機能を用いて次のようにすれば,自分専用の乱数を持つことができます。 100 OPTION ARITHMETIC NATIVE 110 DECLARE EXTERNAL FUNCTION math.random 120 DECLARE EXTERNAL SUB math.randomize 130 CALL RANDOMIZE 140 DECLARE NUMERIC i 150 FOR i=1 TO 20 160 PRINT random 170 NEXT i 180 END 190 200 MODULE math 210 MODULE OPTION ARITHMETIC NATIVE 220 SHARE NUMERIC seed,a,m 230 PUBLIC FUNCTION random 240 PUBLIC SUB RANDOMIZE 250 LET seed=12345 260 LET a=16807.0 270 LET m=2147483647.0 280 EXTERNAL FUNCTION random 290 DECLARE NUMERIC temp 300 LET temp=a*seed 310 LET seed=temp-m*INT(temp/m) 320 LET random=seed/m 330 END FUNCTION 340 EXTERNAL SUB RANDOMIZE 350 LET seed = TIME 360 END SUB 370 END MODULE 留意点は,RNDはFull BASICの予約語なので,利用者定義関数の名前にRNDを用いることができないことです。 なお,十進BASICの英語名はDecimal BASICとしています。 |
└十進BASICの組込み関数RNDにより発生する乱... 荒田浩二 2007/06/08 18:58:39 ツリーへ
Re: ランダム数の周期 |
返事を書く ノートメニュー |
荒田浩二 <knrztrhoel> 2007/06/08 18:58:39 | |
十進BASICの組込み関数RNDにより発生する乱数列は、2147483647を法、16807を乗数、54321を種として線形合同法(乗算合同法)により生成されたものです。
法の2147483647(=2^31-1)と乗数の16807(=7^5)は、良い乱数列を生成する組として知られているものです。 種の54321(=3*19*953)は開発者による任意の値と思われます。 RND関数で得られる乱数列の周期は2147483646(=2^31-2)です。 また、RND関数は周期の二分の一となる1073741823個(=2^30-1個)の乱数を発生した後、当初の乱数との和が1となる数値を順次発生します。 ですから、実用上の周期は1073741823(=2^30-1)でしょう。 また、十進BASICのRANDOMIZE文はTIME関数を利用し、種を 16807*(100*TIME+1) で与えています。 次は、白石先生のプログラムを利用し、関数randomが組込み関数RNDと同様の値を返すようにしたものです。 少しわかりづらいですが、148行のRANDOMIZEはRANDOMIZE文で、それ以外は副プログラム名です。 250行がRANDOMIZE文を実行しない時のRND関数の初期の種、350行がRANDOMIZE文で与えられる種です。 100 OPTION ARITHMETIC NATIVE 110 DECLARE EXTERNAL FUNCTION math.random 120 DECLARE EXTERNAL SUB math.randomize 130 !CALL RANDOMIZE 140 DECLARE NUMERIC i,j 142 FOR i=1 TO 5 143 PRINT random;RND 144 NEXT i 145 PRINT 146 FOR j=1 TO 4 147 CALL RANDOMIZE 148 RANDOMIZE 150 FOR i=1 TO 3 160 PRINT random;RND 170 NEXT i 172 PRINT 173 WAIT DELAY 0.25 174 NEXT j 180 END 190 200 MODULE math 210 MODULE OPTION ARITHMETIC NATIVE 220 SHARE NUMERIC seed,a,m 230 PUBLIC FUNCTION random 240 PUBLIC SUB RANDOMIZE 250 LET seed=54321 ! 初期の種 260 LET a=16807.0 270 LET m=2147483647.0 280 EXTERNAL FUNCTION random 290 DECLARE NUMERIC temp 300 LET temp=a*seed 310 LET seed=temp-m*INT(temp/m) 320 LET random=seed/m 330 END FUNCTION 340 EXTERNAL SUB RANDOMIZE 350 LET seed = 16807*(100*TIME+1) ! RANDOMIZE文で与えられる種 360 END SUB 370 END MODULE |
├!何故か不明、ときどき一致しない時がある。... SECOND 2007/06/10 19:59:10 (修正1回) ツリーへ
Re: 十進BASICの組込み関数RNDにより発生する乱... |
返事を書く ノートメニュー |
SECOND <cszcthjjdj> 2007/06/10 19:59:10 ** この記事は1回修正されてます | |
!何故か不明、ときどき一致しない時がある。
!時刻合せが、これでも不十分なのか。 !ランダム関数Viewer OPTION ARITHMETIC NATIVE !モジュールと揃える。 DECLARE EXTERNAL FUNCTION math.random !モジュール内登録 DECLARE EXTERNAL SUB math.randomize !モジュール内登録 DECLARE EXTERNAL FUNCTION math2.random !モジュール内登録 DECLARE EXTERNAL SUB math2.randomize !モジュール内登録 DO LET t0=TIME PRINT TIME CALL math.RANDOMIZE CALL math2.RANDOMIZE RANDOMIZE LOOP UNTIL t0=TIME PRINT TIME OPTION BASE 0 DIM sum(500),sum2(500),sum3(500) SET WINDOW -20, 520, -1, 5.5 SET LINE COLOR 5 FOR i=0 TO 5 FOR j=2 TO 10 PLOT LINES:-1,LOG10(j)+i; 501,LOG10(j)+i NEXT j NEXT i SET COLOR MIX(15) 0.3,0.3,0.3 DRAW grid0(250,2) PLOT TEXT,AT 300, -0.5: "白石先生、教材サンプル" PLOT TEXT,AT 300, 1.5: "荒田氏、RND 等価乱数" PLOT TEXT,AT 300, 3.5: "現在の十進、内蔵 RND" SET LINE COLOR 1 SET TEXT FONT "",20 SET TEXT BACKGROUND "OPAQUE" LET y0=LOG10(0.6) FOR i=1 TO 1000 LET x=INT(500*math.random) LET x2=INT(500*math2.random) LET x3=INT(500*RND) LET sum(x)=sum(x)+1 LET sum2(x2)=sum2(x2)+1 LET sum3(x3)=sum3(x3)+1 PLOT LINES:x,y0; x,LOG10(sum(x)) PLOT LINES:x2,y0+2; x2,LOG10(sum2(x2))+2 PLOT LINES:x3,y0+4; x3,LOG10(sum3(x3))+4 PLOT TEXT,AT 100, -0.7: STR$(i) IF MOD(i,10)=0 THEN WAIT DELAY 100/(i+100) NEXT i END !-----白石先生、教材サンプル MODULE math MODULE OPTION ARITHMETIC NATIVE SHARE NUMERIC seed, a, m PUBLIC FUNCTION random PUBLIC SUB RANDOMIZE LET seed= 12345 LET a= 16807.0 LET m= 2147483647.0 EXTERNAL FUNCTION random DECLARE NUMERIC temp LET temp= a*seed LET seed= temp-m*INT(temp/m) LET random= seed/m END FUNCTION EXTERNAL SUB RANDOMIZE LET seed= TIME END SUB END MODULE !-----荒田氏、RND 等価乱数 MODULE math2 MODULE OPTION ARITHMETIC NATIVE SHARE NUMERIC seed,a,m PUBLIC FUNCTION random PUBLIC SUB RANDOMIZE LET seed=54321 ! 初期の種 LET a=16807.0 LET m=2147483647.0 EXTERNAL FUNCTION random DECLARE NUMERIC temp LET temp=a*seed LET seed=temp-m*INT(temp/m) LET random=seed/m END FUNCTION EXTERNAL SUB RANDOMIZE LET seed = 16807*(100*TIME+1) ! RANDOMIZE文で与えられる種 END SUB END MODULE |
│├出張で返事おそくなりました。 yoichiro 2007/06/11 09:27:14 (修正1回) ツリーへ
Re: !何故か不明、ときどき一致しない時がある。... |
返事を書く ノートメニュー |
yoichiro <lrmllemwxh> 2007/06/11 09:27:14 ** この記事は1回修正されてます | |
出張で返事おそくなりました。
御返事ありがとうございました。 |
│└RANDOMIZE文がPCの内部時計を参照し種を与え... 荒田浩二 2007/06/12 15:45:57 (修正1回) ツリーへ
Re: !何故か不明、ときどき一致しない時がある。... |
返事を書く ノートメニュー |
荒田浩二 <knrztrhoel> 2007/06/12 15:45:57 ** この記事は1回修正されてます | |
RANDOMIZE文がPCの内部時計を参照し種を与えていることは間違いないのですが、どうもTIME関数とは違う方法で時刻を取得しているようです。
RANDOMIZE文では通常 16807*(100*TIME+1) の数値式で種を与えているはずですが、RANDOMIZE文を実行する時刻によっては2%〜50%程度の割合で、16807*(100*(TIME-0.01)+1) という数値式で種を与えることがあります。 もっともこのことは「疑似乱数の系列の出発点を予測できないものにする。」というRANDOMIZE文の本来の目的からすれば、むしろ好ましいことと言えるでしょう。 次のプログラムは、RND関数と同様の値を返す関数rnd2を定義し、両者に相違が生じた場合に修正した種を与えるようにしたものです。 REM ** RANDOMIZE文で与える種との相違 ** LET seed=54321 ! RANDOMIZE文を実行しないときの初期の種 FUNCTION rnd2 ! RND関数と同様の値を返す関数 LET seed=MOD(16807*seed,2147483647) ! 16807=7^5 , 2147483647=2^31-1 LET rnd2=seed/2147483647 END FUNCTION LET c=0 LET t0=TIME DO WHILE t0+1>TIME ! 1秒間実施 DO ! RANDOMIZE文の前後でTIME関数の値が更新されていないことを確認 LET t1=TIME RANDOMIZE LET t2=TIME LOOP UNTIL t1=t2 LET seed=16807*(100*t2+1) ! RANDOMIZEと同様の種を与える数値式 LET r=RND LET r2=rnd2 IF ABS(r-r2)>1E-12 THEN ! RNDとrnd2の値が違う時 PRINT USING "TIME #####.## #####.##":t1,t2 PRINT USING "RND = .############### , ##########(種)":r,INT(r*2147483647+0.5) PRINT USING "rnd2= .############### , ##########(seed)":r2,seed LET seed=16807*(100*(t2-0.01)+1) ! 修正した種を与える数値式 LET r3=rnd2 PRINT USING "修正= .############### , ##########(seed)":r3,seed LET c=c+1 END IF WAIT DELAY 0.02 LOOP PRINT "相違";c;"回" END |
│ ├補足 荒田浩二 2007/06/12 16:50:44 ツリーへ
Re: RANDOMIZE文がPCの内部時計を参照し種を与え... |
返事を書く ノートメニュー |
荒田浩二 <knrztrhoel> 2007/06/12 16:50:44 | |
補足
上に投稿した「** RANDOMIZE文で与える種との相違 **」というプログラムを実行すると、「相違 0 回」と出力される時は数回繰り返しても同じ結果になると思います。 どうもRANDOMIZE文を実行する時刻によって、この相違が生じるかしないかが決定されるようです。 そして、相違が生じる時刻には規則性がありそうです。 次のプログラムは、RANDOMIZE文が通常とは違う種を与えるか与えないかを調査した結果を出力するものです。 「なし」の時間帯に上のプログラムを実行しても「相違 0 回」になります。 参考までに、この調査を実施したのは2006年12月5日ですので十進BASICのバージョンもその時点のものです。 その時のPCのOSは、Windows XP SP2 です。 別のPCやOSでは、違う結果になるかもしれません。 なぜこのような結果になるのか、どなたか説明できる方いらっしゃいますか? REM ** RANDOMIZE文調査結果 ** DECLARE FUNCTION times$ PRINT "RANDOMIZE文を実行して与えられる種が、" PRINT "16807*(100*TIME+1)と相違する場合の有無" PRINT USING "########### (#####.##) >#####":"実行時刻","TIME","相違" FOR i=8 TO 22 LET t1=0.01*2^i LET t2=2^(i-6) PRINT USING "########### (#####.##)〜 なし":times$(t1),t1 PRINT USING "########### (#####.##)〜 あり":times$(t2),t2 NEXT i LET t1=0.01*2^i PRINT USING "########### (#####.##)〜 なし":times$(t1),t1 FUNCTION times$(p) ! TIME$で秒を小数まで表示 LET hh$=USING$("%%",INT(p/3600)) LET mm$=USING$("%%",MOD(INT(p/60),60)) LET ssss$=USING$("%%.##",MOD(p,60)) LET times$=hh$&":"&mm$&":"&ssss$ END FUNCTION END |
│ │└RANDOMIZEの実体は 白石 和夫 2007/06/12 17:32:44 (修正2回) ツリーへ
Re: 補足 |
返事を書く ノートメニュー |
白石 和夫 <fbdfvqwhki> 2007/06/12 17:32:44 ** この記事は2回修正されてます | |
RANDOMIZEの実体は
procedure MyRandmize; var x:extended; begin seed:=int(mytime*100)+1; x:=random; end; となっています。 MytimeはTIME関数の実体です。 |
│ │ └RANDOMIZEも種が、TIME関数と同一と、いうこ... SECOND 2007/06/12 18:00:26 (修正1回) ツリーへ
Re: RANDOMIZEの実体は |
返事を書く ノートメニュー |
SECOND <cszcthjjdj> 2007/06/12 18:00:26 ** この記事は1回修正されてます | |
RANDOMIZE も 種が、TIME関数と同一と、いうことですか。
少数下第3位目の、システム時刻は、どう処理されているのでしょうか。 |
│ │ └MyTimeは拡張精度なので,それが差がでる原... 白石 和夫 2007/06/12 18:16:23 ツリーへ
Re: RANDOMIZEも種が、TIME関数と同一と、いうこ... |
返事を書く ノートメニュー |
白石 和夫 <fbdfvqwhki> 2007/06/12 18:16:23 | |
MyTimeは拡張精度なので,それが差がでる原因かも知れません。
function roundext(x:extended):extended;assembler; asm fld x frndint end; function MyTime:extended; var t:double; begin t:=time; t:=t-INT(t); result:=RoundExt(t*8640000)/100.; end; |
│ │ └先生のリストで、同値のMytimeに挟まれるMy... SECOND 2007/06/12 22:06:23 (修正5回) ツリーへ
Re: MyTimeは拡張精度なので,それが差がでる原... |
返事を書く ノートメニュー |
SECOND <cszcthjjdj> 2007/06/12 22:06:23 ** この記事は5回修正されてます | |
先生のリストで、同値のMytime に挟まれるMytime の揺らぎについて、考えてみました。
frndint コントロール・ワード、RC ビットが、変化しているとしか、思えません。 こんなものが、勝手に動いたりするものでしょうか。 バグが、このビットへ、時刻などを、書き込んでいれば、荒田氏の調査結果のように なるかも、知れませんが・・・ 自分で読めなかったので、勝手に注釈などを、 書き込んでしまいました。ご容赦下さい。 function roundext(x:extended):extended; assembler; asm fld x // xを、コプロセッサーへ置数。 frndint // 整数へ丸め(コントロール・ワード RC(bit 11~10)による。 00:近似値へ 01:−∞方向へ 10:+∞方向へ 11: 0方向へ) end; function Mytime:extended; var t:double; begin t:=time; // day 単位の実数 t:=t-INT(t); // day 単位の実数の小数部 result:=RoundExt(t*8640000)/100.; // 0.01 秒単位の実数→ 整数へ丸め→ 秒単位の実数(小数下2桁止め) end //RANDOMIZEの実体は procedure MyRandmize; var x:extended; begin seed:=INT(mytime*100)+1; x:=random; end; //となっています。 //Mytimeはtime関数の実体です。 |
│ │ └整数丸めコントロール・ワードが勝手にゆら... 白石 和夫 2007/06/13 07:23:02 (修正2回) ツリーへ
Re: 先生のリストで、同値のMytimeに挟まれるMy... |
返事を書く ノートメニュー |
白石 和夫 <fbdfvqwhki> 2007/06/13 07:23:02 ** この記事は2回修正されてます | |
整数丸めコントロール・ワードが勝手にゆらぐことはありません。
正確に検証したわけではありませんが,おそらく,拡張精度と倍精度の仮数部ビット数の違いです。 2進モードのとき,Mytimeは倍精度に丸められてTIME関数の値になります。このとき,微妙な差が生じることがありえます。 |
│ │ └私のパソコンでも荒田氏と同様の時刻の規則... SECOND 2007/06/13 07:53:00 (修正2回) ツリーへ
Re: 整数丸めコントロール・ワードが勝手にゆら... |
返事を書く ノートメニュー |
SECOND <cszcthjjdj> 2007/06/13 07:53:00 ** この記事は2回修正されてます | |
私のパソコンでも荒田氏と同様の時刻の規則性が
現れています。環境は、V599 と Win98SE です。 30秒ほど、違いますが、概ね、バイナリーシフトな 感じで、間隔が、広がって行きます。 |
│ └DELETED SECOND 2007/06/12 17:23:39 (削除) ツリーへ
Re: RANDOMIZE文がPCの内部時計を参照し種を与え... |
返事を書く |
SECOND <cszcthjjdj> 2007/06/12 17:23:39 ** この記事は削除されました | |
|
└リストの中で、"田"が"川"になっていた事を... SECOND 2007/06/18 06:52:15 ツリーへ
Re: 十進BASICの組込み関数RNDにより発生する乱... |
返事を書く ノートメニュー |
SECOND <cszcthjjdj> 2007/06/18 06:52:15 | |
リストの中で、"田"が"川"になっていた事をお詫びします。
|