rand()のバグ?

[上に] [前に] [次に]
える 2000/01/21(金) 01:44:20
This is perl, version 5.005_03 built for MSWin32-x86-object
を使って以下のスクリプト
#-------------------
$t=time;
srand($t);
for($j=0;$j<10;$j++){
$r=int(rand(10));
print ("$r\t");
}
#-------------------
を連続して実行したところ、

D:\>perl rand.pl
7       1       8       4       7       5       3       9       0       5

D:\>perl rand.pl
7       4       4       1       1       6       4       8       5       3

D:\>perl rand.pl
7       4       4       1       1       6       4       8       5       3

D:\>perl rand.pl
7       4       4       1       1       6       4       8       5       3

D:\>perl rand.pl
7       8       9       9       4       7       4       7       0       1

のように、先頭が常に7でした。また、かなり時間をおいてからもう一度やってみると、今度は先頭が常に4でした。

 どうしてこのようになってしまったのでしょうか。OSはWindos98SEです。

B-Cus 2000/01/21(金) 02:12:20
time の値をそのまま乱数の seed として使うのはダメです。
乱数としての品質が低いから。なので、
 srand(time()^($$+($$<<15)))
とか。

> できれば高価なラクダ本ではなく、またネット上で手に入れば最高です。
srand(time()^($$+($$<<15))) はラクダ本に載ってます。
sysread についても載っています。perl 標準ライブラリについても、
5.003 時点 (かな?) のものが詳しく説明されています。
 http://www.att.or.jp/perl/man/index.html
の記述より詳しいです。金をけちって他人に質問し続けるより、
買った方がよいのでは?

# そーいや「perl モジュールガイド」とかいう本もあったかも。

mm 2000/01/21(金) 04:01:43
以前から rand の件で疑問だったのですが、Win32の $$ って何が格納されてるのでしょうか?
Win95で $$ の値を表示するスクリプトをちょっと試したら、
個々に別ウインドウを開いて実行した場合は、異なる値になるんですが、
各ウインドウをいちいち閉じて再実行した場合には同じ値になることがあり、
同じDOS窓内でコマンドラインから何度か実行させたら、すべて同じ値になります。
ウインドウハンドルに関係がありそうですが…?

いずれにしても、Win では、srand(time()^($$+($$<<15))) は必ずしも安全とは言えない
ように思うのですが?


>time の値をそのまま乱数の seed として使うのはダメです。
B-Cus さんの発言は、影響力が大きいので(笑い)、念のため補足すれば、
「乱数としての品質が低」くてもいいなら、必ずしもダメではありません。

srand の引数の値が同じなら、rand は常に同じ数列を返します。
従って、srand 又は srand(time) とした場合、
(1) 1秒以内に実行されたプロセスでは、rand は同じ数列を返します。
(2) time の値は予測可能なので、これが分かれば rand が生成する数列も予測可能となります。
このため、セキュリティに関わるなどの理由で、これらが問題となる場合には、
危険だということです。

mm 2000/01/21(金) 04:33:35
>ウインドウハンドルに関係がありそうですが…?
Win32ではプロセスハンドルというのもあるようです。

並行していない連続するプロセスでは、$$ の値が同じになってもいいのであれば、
Winでも $$ の使用は問題ないのかも知れません。
# unixのプロセス番号が分かってないのですが…(苦笑)

[上に] [前に] [次に]