乱数の生成についてNo.05514
三丁目の秀さん さん 07/04/28 18:24
 
今日は、はじめまして三丁目の秀さんです宜しくお願いいたします。
秀丸エディタFloat-Macro(統合)
V7.00 Bata2にて

12文字の16進数の乱数を生成したく思い下記のようにマクロを組みましたが
実行すると
$numには1回目に生成した同じ文字列が代入されてしまい、思い通りに振舞ってくれ
ません。
コメントアウトしている//$numからコメントアウトを外して実行すると、思い通りに
動きます文法的に間違っていますでしょうか?
ご教示お願いします。

setfloatmode 1;    //浮動小数点数モードにする
loaddll "hidemath.dll";
if(!result){
 message "hidemath.dllのロードに失敗しました";
 endmacro:
 }else{
  call RAND;
}
freedll;

RAND:
#i = 0;
$num = "";
while( #i < 12){
 #dummy = dllfunc( "Randomize" );
 #rand = dllfunc( "Random" );
 #rand_org = #rand;
 #rand = #rand / 16;
 #rand = dllfunc("Floor", #rand);
 #rand_org = #rand_org - (#rand * 16);
 $str[#i] = hex(#rand_org);
 $num = $num + $str[#i];
 #i = #i + 1;
//message $num;  //このコメントアウトを外すと、もう一箇所の$numにも12文字の1
6進数(文字変換した)が代入されます。
}
message $num;  //FFFFFFFFFFFFとか111111111111になってしまいます?

[ ]
RE:05514 乱数の生成についてNo.05515
h-tom さん 07/04/28 19:08
 

h-tom です。

>12文字の16進数の乱数を生成したく思い下記のようにマクロを組みましたが
>実行すると
>$numには1回目に生成した同じ文字列が代入されてしまい、思い通りに振舞ってくれ
>ません。
>コメントアウトしている//$numからコメントアウトを外して実行すると、思い通りに
>動きます文法的に間違っていますでしょうか?
文法的には間違ってませんが、"Randomize"の使い方が問題です。

ヘルプには、
>Randomizeは、パソコンの内部時計を使って疑似乱数生成のための
>初期値を狂わせます。
と、あります。

内部時計のどのくらいまで使っているかわかりませんが、それほど細かい所
までは使っていないでしょう。
つまり、マクロの実行速度を考えると、ほぼ同じ時刻を使って初期化している
ことになります。
初期値が同じなので、同じ数字しか取り出せていないのでしょう。

>乱数を得たい場合には、まず、Randomize関数を最低1回呼んで、
>その後Random関数を使って乱数を得るようにしてください。
とあるように、Randomizeの実行は1回でいいです。

message文を有効にすると、ランダムになるのは、waitがかかるため、
乱数の初期値がずれるためですね。

ということで、
 #dummy = dllfunc( "Randomize" );
を、while文の前に移動させればいいでしょう。

[ ]
RE:05515 乱数の生成についてNo.05516
三丁目の秀さん さん 07/04/28 19:23
 
h-tom さんお世話になります。

ご教示ありがとうございました。
毎回dllfunc( "Randomize" )を実行しないと乱数が得られないものと思い込んでいま
した。

[ ]
RE:05516 乱数の生成についてNo.05517
三丁目の秀さん さん 07/04/28 21:17
 
h-tomさんにご教示してもらいすんなり行くかと思ったのですが
まともな乱数を得ようとSLEEP関数を追加して、希望の実行結果は得られたのですが

秀丸のエラーメッセージ”DLLがロードされていないのにdllfunc関数が使われました
”となってしまいます。
上記の文言でGoogle検索したら2件ヒットしまして確認し、RAND関数内でもう一度loa
ddll "hidemath.dll"を行いましたが
解消できません、掲題の内容とは別件になりますが、原因等分かる方が居られました
らご教示願います。
※ 田楽DLLを入れていたのでとりあえず削除してみましたが芳しくありません。

//MFC_HEADER.MAC
//秀丸でMFCのヘッダーを自動生成するマクロ
//2007/04/28
//三丁目の秀さん

setfloatmode 1;    //浮動小数点数モードにする
loaddll "hidemath.dll";
if(!result){
    message "hidemath.dllのロードに失敗しました";
    endmacro:
    }else{
        #n = 12;
        call RAND #n;
        $num1 = $num;
        call SLEEP;
       
        #n = 8;
        call RAND #n;
        $num2 = $num;
        call SLEEP;
       
        #n = 4;
        call RAND #n;
        $num3 = $num;
        call SLEEP;
       
        #n = 4;
        call RAND #n;
        $num3 = $num;
        call SLEEP;
       
        #n = 4;
        call RAND #n;
        $num4 = $num;
        call SLEEP;
       
        #n = 12;
        call RAND #n;
        $num5 = $num;
       
        message "#if !defined(AFX_" + $num1 + "_H__" + $num2  + "_" + $num3
+ "_" + $num4 + "_" + $num5"__INCLUDED_)";
        freedll;
    }

RAND:
    #i = 0;
    $num = "";
    #dummy = dllfunc( "Randomize" );
    while( #i < #n){
        #rand = dllfunc( "Random" );
        #rand_org = #rand;
        #rand = #rand / 16;
        #rand = dllfunc("Floor", #rand);
        #rand_org = #rand_org - (#rand * 16);
        $str[#i] = hex(#rand_org);
        $num = $num + $str[#i];
        #i = #i + 1;
    }
return $$num;

SLEEP:
    #i = 0;
    while( #i < 5000){
        #i = #i + 1;
    }
return;

[ ]
RE:05517 乱数の生成についてNo.05518
h-tom さん 07/04/28 21:29
 

h-tom です。

>秀丸のエラーメッセージ”DLLがロードされていないのにdllfunc関数が使われました
>”となってしまいます。
>上記の文言でGoogle検索したら2件ヒットしまして確認し、RAND関数内でもう一度loa
>ddll "hidemath.dll"を行いましたが
>解消できません、掲題の内容とは別件になりますが、原因等分かる方が居られました
>らご教示願います。

前のメールで、指摘しようかと思って忘れてました。
メインルーチンとサブルーチンの間にendmacroを入れましょう。
>        message "#if !defined(AFX_" + $num1 + "_H__" + $num2  + "_" + $num3
>+ "_" + $num4 + "_" + $num5"__INCLUDED_)";
>        freedll;
>    }
endmacro; //これを追加
>RAND:

そうしないと、メインルーチン終了後、そのままサブルーチンを実行していま
います。
その為、freedllの後に、RANDの中で"dllfunc"している為、エラーになって
います。

[ ]
RE:05518 乱数の生成についてNo.05519
三丁目の秀さん さん 07/04/28 22:09
 
お世話になります、三丁目の秀さんです
>そうしないと、メインルーチン終了後、そのままサブルーチンを実行していま
>います。
>その為、freedllの後に、RANDの中で"dllfunc"している為、エラーになって
>います。

そうだったのですね、秀丸マクロでendmacroは結構重要な意味を持つのですね。
お蔭様で所望していた物が出来たので取り合えずコードを載せます
初めて秀丸マクロを組んだので何かおかしな所がありましたらご指摘願います。

//MFC_HEDAR.MAC
//秀丸でMFCのヘッダーを自動生成するマクロ
//2007/04/28
//三丁目の秀さん

setfloatmode 1;    //浮動小数点数モードにする
loaddll "hidemath.dll";
if(!result){
    message "hidemath.dllのロードに失敗しました";
    endmacro:
    }else{
        #n = 12;
        call RAND #n;
        $num1 = $num;
        call SLEEP;
       
        #n = 8;
        call RAND #n;
        $num2 = $num;
        call SLEEP;
       
        #n = 4;
        call RAND #n;
        $num3 = $num;
        call SLEEP;
       
        #n = 4;
        call RAND #n;
        $num3 = $num;
        call SLEEP;
       
        #n = 4;
        call RAND #n;
        $num4 = $num;
        call SLEEP;
       
        #n = 12;
        call RAND #n;
        $num5 = $num;
       
        call ADD_NEW_FILE $num1 $num2 $num3 $num4 $num5;
       
        freedll;
    }

endmacro;

RAND:
    #i = 0;
    $num = "";
    #dummy = dllfunc( "Randomize" );
    while( #i < #n){
        #rand = dllfunc( "Random" );
        #rand_org = #rand;
        #rand = #rand / 16;
        #rand = dllfunc("Floor", #rand);
        #rand_org = #rand_org - (#rand * 16);
        $str[#i] = hex(#rand_org);
        $num = $num + $str[#i];
        #i = #i + 1;
    }
return $$num;

SLEEP:
    #i = 0;
    while( #i < 5000){
        #i = #i + 1;
    }
return;

ADD_NEW_FILE:
        openfile "header.h";
        insert "#if !defined(AFX_" + $num1 + "_H__" + $num2  + "_" + $num3 +
 "_" + $num4 + "_" + $num5"__INCLUDED_)";
        insert "\x0A";
        insert "#define AFX_" + $num1 + "_H__" + $num2 + "_" + $num3 + "_" +
 $num4 + "_" + $num5 + "__INCLUDED_";
        insert "\x0A";
        insert "#include strdaf.h";
        insert "\x0A";
        insert "#if _MSC_VER > 1000";
        insert "\x0A";
        insert "#pragma once";
        insert "\x0A";
        insert "#endif // _MSC_VER > 1000";
        insert "\x0A";
        insert "\x0A";
        insert "\x0A";
        insert "#endif // !defined(AFX_" + $num1 + "_H__" + $num2 + "_" + $n
um3 + "_" + $num4 + "_" + $num5 + "__INCLUDED_)";
return;

[ ]
RE:05519 乱数の生成についてNo.05521
三月 さん 07/04/29 07:46
 
loaddll "hidemath.dll";
の成功直後にRandomizeを一度すれば、
SLEEPを入れる必要なないと思われます。

loaddll "hidemath.dll";
if(!result){
} else {
    #dummy = dllfunc( "Randomize" );
    :
のように。


[ ]
RE:05521 乱数の生成についてNo.05522
三丁目の秀さん さん 07/04/29 08:34
 
おはようございます。三日月さん。
ご指摘ありがとうございます。

>loaddll "hidemath.dll";
>の成功直後にRandomizeを一度すれば、
>SLEEPを入れる必要なないと思われます。

確かにその通りにしましたら、SLEEPを入れなくても乱数が生成できました?
なぜそうなるのか解説していただけたら幸いです。
宜しくお願いいたします。

[ ]
RE:05522 乱数の生成についてNo.05523
Iranoan さん 07/04/29 15:27
 
 三丁目の秀さん今日は、Iranoan です。
> >Randomizeを一度すれば、
> >SLEEPを入れる必要なないと思われます。
>
> 確かにその通りにしましたら、SLEEPを入れなくても乱数が生成できました?
> なぜそうなるのか解説していただけたら幸いです。
 詳細は、C 言語の本で、rand(), srand() 関数の仕様を御覧頂くのが確実だ
と思います。理由は、公開されているので HideMath.dll のソースを御覧いた
だければ解りますが、Random(), Randomize() 関数が上記の関数を単純に呼び
出すラッパだからです。

 これでは不親切なので、簡単に説明しておくと、まずコンピュータで生成さ
れる乱数は、実際には厳密な意味での乱数ではありません。導出方法によって
変わりますが、sin 等と同じある周期を持った周期関数です。またコンピュー
タなので、実際には算術計算をしているだけなので、プログラムを実行するた
びに、異なる乱数列を得るには、乱数を計算するときの元のなる数値 (一般に
乱数の種と呼ばれる) を変えてやる必要があります。(こうしないと、毎回同
じ乱数列が生成される。)この乱数の種を指定する関数が、srand() です。
 そのような性質から、プログラムの開始から終了までに、何度も srand()
を呼び出してはいけません。それでは乱数になりません。また周期と同程度の
オーダだけ乱数が必要なら、より長い周期の乱数アルゴリズムを使用する必要
があります。このようなことから、理数系の厳密な結果が必要な場合、rand()
関数が使われていたら、結果を疑ったほうが良いです。rand() は整数値だし。

[ ]
RE:05523 乱数の生成についてNo.05524
三丁目の秀さん さん 07/04/29 21:42
 
Iranoanさん三丁目の秀さんです
詳しい解説ありがとうございます、乱数は実務では使わないのですっかり
忘れていました。

[ ]