ab.com コミュニティ
https://www.activebasic.com/forum/

[AB4] 乱数発生アルゴリズム「Mersenne Twister」
https://www.activebasic.com/forum/viewtopic.php?t=517
ページ 11

作成者:  Sinryow [ 2005年12月02日(金) 03:31 ]
記事の件名:  [AB4] 乱数発生アルゴリズム「Mersenne Twister」

Mersenne Twister(MTと略す)とは,松本眞(現広島大教授)・西村拓士(現山形大助手)氏による乱数発生アルゴリズムです。
詳細はこちらをどうぞ→Mersenne Twister Home Page

少なくとも,ABで使っている乱数よりは性能がいいそうです。
また,不必要に乗算を使用しないためかABの乱数よりも少しだけ速いです。

<処理時間比較>
MT法 ABのrand (時間:msec)
100,000回 71 76
500,000回 371 394
1,000,000回 759 878
5,000,000回 3855 4276

大学の授業に出てきたのですが,興味があったので原版のCプログラムをABに移植してみました。
※関数リファレンスは省略しました。使用法ドキュメントをお読み下さい。

※補足
AB4用ですが,「/* ~ */」型のコメントを「' ~ 」にして,Dim文中で変数の初期化を行わなければ,AB2・3でも使えるかもしれません。

作成者:  河川屋 [ 2005年12月13日(火) 02:15 ]
記事の件名: 

> 少なくとも,ABで使っている乱数よりは性能がいい
> ABのrand

まず、比較が間違っています。
Abにおける正式仕様はrandではなくてRnd。
randは隠し関数なので、いつ、こっそり変えられても文句を言ってはならないのです。
だから、Rndで見ないとなんない。

>>>>
ヘルプより。
乱数は 0 以上、1 未満の実数で表されます。

乱数関連のABソース再掲。(AB 4.12.01)
Function Rnd() As Double
Rnd=CDbl(rand()*rand() Mod 100000)/100000
End Function
Dim _System_RndNext As DWord
Function rand() As DWord
_System_RndNext=_System_RndNext*1103515245+12345
rand=((_CUDbl(_System_RndNext)/65536) As QWord) Mod 32768
End Function
>>>>>

以上より、ABのRndはハチャメチャもいいところ。
まず、ヘルプによれば、どう見ても、
・0~1の一様乱数を返し、その精度は倍精度相当である。
としか読めません。でも、
>Rnd=CDbl(rand()*rand() Mod 100000)/100000
であるから、「10進5桁の一様乱数」なんです。 ただしこれは許容するとします。
(ヘルプからこういう仕様であると判断することは不可能です。でも許容するものとします。)
で、ホントに「10進5桁の一様乱数」なのか?とんでもない。
「10進5桁の一様乱数」イコール0~99999の整数の一様乱数 ですよね?
で、rand()は、0~32768の整数の一様乱数 だから、
(rand()*rand() Mod 100000) の1の位を考えればはっきりしています。
1の位が偶数である確率:75%。 奇数である確率:25%。
こんなに偏った数値を返すのにランダムに返すとは何のこっちゃ!そりゃないよ。
Function Rnd() As Double
Rnd=(rand()+rand()\32768)/32768
End Function
としたほうがどれだけマシなことか。
(単精度の範囲で一様乱数をキープ。でも、結果は単精度という注釈必要。)


あと、
Function rand() As DWord  ですが、こちらは、一応は、混合合同法という
古典的ながらそれなりに効力のあるアルゴリズムなのでコメント無し。
ただし、
Function rand() As DWord
_System_RndNext=_System_RndNext*1103515245+12345
rand=((_CUDbl(_System_RndNext)/65536) As QWord) Mod 32768
End Function
というのは何か変で、
Function rand() As Int64
_System_RndNext=_System_RndNext*1103515245+12345
_System_RndNext=_System_RndNext Mod 2^32
rand=((_CUDbl(_System_RndNext)/65536) As QWord) Mod 32768
End Function
と組まない限り、桁オーバーでアウト、と見るのが普通なんだろうけど、何で桁オーバーせず動くの?
ヘルプ見ても、何故桁オーバーしないか、まるでわからん。

作成者:  Sinryow [ 2005年12月13日(火) 08:12 ]
記事の件名: 

引用:
Mersenne Twisterについては、以前このフォーラムでSinryow氏によりAB版に移植されたものが公開されていましたが(http://www.discoversoft.net/forum/viewt ... 5%F3%A5%CC)、
その使用法について質問させていただきます。

MTの乱数を初期化する際、32ビットより長い初期シードを用いたい場合は、init_by_array()により任意長の配列を用いて初期化することができるとされていますが、具体的にはどのように記述するのでしょうか?

自分としては、128ビットの値を32ビット×4の配列にし、それを初期シードとしてMTに渡したいと思っているのですが、init_by_array()の引数をどのように記述すれば良いのかが良くわからないのです。

(ABには直接関係ない内容かとは思いましたが)よろしくお願いいたします。
以下のようになるかと思います。試していませんが。
コード:
Dim Seed[ELM(4)] As DWord
Seed[0] = &H83024923
Seed[1] = &H14325091
Seed[2] = &H01328943
Seed[3] = &H65129462
init_by_array(Seed, 4) ' 「4」は配列の要素数

作成者:  MT [ 2010年6月06日(日) 20:16 ]
記事の件名:  MT厨

MTはええねMT

ページ 11 全ての表示時間は UTC+09:00 です
Powered by phpBB® Forum Software © phpBB Limited
https://www.phpbb.com/