ぎょーむ日誌 2000-09-06
2000 年 09 月 06 日 (水)
- 0650 起床.
4 時間ぐらい寝たかなあ.
眠い.
- えーと,
昨晩というか
今朝というか,
ともかく寝る前は 0200 近くまで
小川モデリングがらみの
コードをあれこれといじっており,
眠気が指さないので
昔作った OHP 用トランスペアレンシーの
廃棄作業準備作業,
という
頭は使わない単純労働を 0300 ごろまで続けてた.
- 朝飯・弁当の準備.
シャワー.
ひげそり.
朝飯.
出発の準備.
- 0745 自宅発.
曇り.
涼しい.
0805 東京モノレイル流通センター発.
浜松町の気温 20 ℃.
よしよし.
0825 研究所着.
- プリンターが空いてるうちに
kubolib なる怪しげなコードを
まとめて印刷.
最近,
自分でも全貌がよくわからなくなりつつある.
危機的かも.
印刷したら,
A4 の 26 穴バインダーに装着できる
透明な袋にいれて
自家製リファレンスマニュアルとする.
大量のトランスペアレンシーを処分したんで,
こういうバインダーとかが無闇に余っているのである.
- 昨日のぎょーむ日誌で一様乱数の「種」がどうのこうの,
と書いてたことに関して
竹中さんが ce-ml にコメントを投稿してくださる.
以下はそれに対する私の返事の一部
(ちょっと編集).
まずは問題提起部.
Subject: Re: [ce-ml 71] initialization of random number series.
Date: Wed, 06 Sep 2000 10:58:50 +0900
(略)
From: "TAKENAKA, A." <takenaka@nies.go.jp>
Date: Wed, 06 Sep 2000 09:37:45 +0900
> (9月5日の「日誌」から)
> > 「乱数の種」 をシステムクロック で初期化するように Ranu
> > クラスを変更してみる. システムクロックとは, Unix の場合
> > 1970 年 1 月 1 日からの経過秒のことで,いま現在だと 9 億
> > 8617 万秒あたりの値を示す. これを用いると各時刻で異なる
> > 初期値が得られる.
>
> 時刻を乱数の種に使うのはよく使われる手ですが,乱数を利用する
> プログラムが1秒以下で終わってしまうようなごくごく小規模のも
> のの場合,続けざまに実行すると,同じ時刻が乱数の種となり,同
> じ乱数系列が発生してしまうことがあります.
蛇足の補足しますと,「同じ乱数系列が発生」問題というのは,ホ
ントは毎回毎回デタラメな乱数がいくつか必要なのに,何べんプロ
グラムを再実行しても
3→1→4→1→5→9→2→……
というような「決まった順番でデタラメな数がでる」という状態で
す.これは上で議論してる「乱数の種」がいつも同じ値であるため
に生じる問題です.
- というふうに,
システムクロックなんか使うのはヤバいんじゃないの,
ということで以下のような解決策を
示してくださったわけである.
で,
昨日の作文ではちゃんと書いてなかったけど,
自分でもそれをやってました,
と答える私.
> これを避けるために,私の自作の乱数ライブラリ(C++)では,乱数
> 発生オブジェクトが廃棄されるときに,最後にひとつ乱数を発生して
> カレントディレクトリのmyrandom.iniというファイルに書き出してい
> ます.
>
> 乱数発生オブジェクトは,生成時に,このファイルを探しに行き,見
> つかったらその内容を読み込んで,これと時刻情報の演算で得られる
> 値を乱数の種にします.こうすれば,0.1秒しかかからないプログラム
> を繰り返し実行するような場合も大丈夫です.
たしかにこの方法を採用すると上の問題が避けられます.で,じつ
はシステムクロックで乱数の種を初期化する,という方法を採用す
る前は,この方法使ってました.今回はそれに加えてファイルいら
ずの方法を加えて,
- 一様乱数クラス Ranu はデフォルトではシステムクロックで初
期化される.
- (このステップは省略化) さらに Ranu::Initialization( "ファ
イル名" ) を呼び出す,あるいは Ranu( "ファイル名" ) で
オブジェクトを作ると,指定したファイルから乱数の種を読み
込む.
- オブジェクトが破壊時に,2. の操作をやっていたならば,乱
数の種を元のファイルに上書きする.ファイルから読みこんでなけ
ればそのまま終了.
- ま,
こういうのは「どっちか一方」
ではなく,
良さそうな方法のどちらも
採用できるようにしておいたほうが
無難,
というつもり.
- で,
「一秒間に何度も呼ばれるような短いプログラム」
が問題にされてるわけだけど,
そうなると C/C++ ではなく
Perl なんかはどうなるだろう,
という疑問が生じてくる
(Perl で書いたプログラムはすぐに終わる
小さいものが多いから).
途中すこし略して
……
さて「すぐに終了するプログラム」を書く言語の代表格はと言えば,
(このメイリングリストの皆様もよく使っておられる) Perl という
ことになるかと思います.
竹中さんのご指摘で不安になったんで,さきほど
perl -le 'print rand;'
というのを 10000 回ほど呼び出す実験をやってみました.全体で
100 秒ぐらいかかったんで (う,遅い) ,1 秒あたり 100 回ぐら
い乱数が生成されたようです.
その結果なんですけど,一様検定とかちゃんとやってないんですけ
ど,図示してみたところ「ま,ちゃんと一様じゃない」 (……いい
かげんな) という程度には動作してくれてるようです.
- Perl5.005 で実験してみると,
同じ乱数系列ばかり生じることはなさそう,
とわかって一安心している.
- Perl ではどうやって乱数の種を初期化してるんだろう,
とあれこれと勝手な憶測を書いてるうちに
(この部分は引用略),
不安になったので
ちょっと調べてみた.
…… といいかげんなことばかり書いてると不安になったんで,ネッ
ト上で情報を漁ってみました.それで見つけた Perl の関数リファ
レンス
http://www.ns.kogakuin.ac.jp/~b196189/reference/perl/perl.html
によると (これはラクダ本か何かの複写だろうか?)
srand( time | $$ )
による初期化を推奨してるようですね.この ( ... ) 内の奇怪な
暗号は
「システムクロック,
それから今のプロセス id のビット単位の論理和」
という意味です.なーんで論理和取るとよいの ? か私には見当も
つきませんけど,プロセス id も利用するのはこれもうまい手です
よね.
- ……
と,
まぁいろいろ勉強になりました.
- 後から竹中さんが Perl を解説した
「青ラクダ本」
調べてくださって,
srand( time ^ ($$ + ($$ << 15)) )
というようなやり口が書かれている
と紹介してくださった.
これはラクダ本なくとも
perldoc -f srand
で同じような解説を読むことできる
(もっと病的な「初期値取得法」の例も掲載されてる).
- いずれにせよシステムクロックだけでなく
プロセス id の利用が有効とわかった.
そこで kubolib に含まれる
ranu.h (一様乱数生成する Ranu クラスの定義)
においても,
getpid()
関数も利用して
乱数の種を初期化することにした.
関数 getpid()
は
POSIX 関連を取り扱う
<unistd.h>
に含まれている.
- 論理和 (
|
)とか
排他的論理和 (^
)を取るのも,
なんとなーく
あまりよいとは思えなかったんで,
実験的に
time % getpid()
という量を使っている.
演算子 %
は剰余である.
- 午前中はメイル書き数通と
kubolib の点検で終わってしまった.
- 今日は昼飯食ってる最中から
どんどん眠くなる.
うう.
気絶しそう.
- 「Perl によるオブジェクト指向プログラミング」
という少々奇怪に思える世界について
勉強する.
小川の樹木名 (学名・和名・略号・色指定)
の相互変換モジュールはクラス化せんといかん,
という気がしてるんで
……
- Effective Perl などの本を参考にしながら,
tree_name.pm というのを
少しずつ構築していく.
- Perl によるオブジェクト指向の実装とは
Perl モジュール機能を流用・拡張したものなのである.
「クラス名」は
package TreeName;
というふうに宣言してみたり.
- コンストラクターは
new
サブルーチン
として書かれる.
基本形はこうである.
sub new {
my $class = shift;
my $self = {};
(…… あーだこーだ ……)
bless $self, $class;
}
…… ``bless
'' なんて怪しげな予約語もつ
プログラミング言語は Perl をおいて他にあるまい.
Unix で普及してるロールプレイングゲイム
NetHack を好む人にとっては
楽しいのかもしれないけど.
- オブジェクト指向な Perl モジュールの輪郭を
(あれこれ実験しながら)
ゆっくりと整えつつ,
名前変換のアルゴリズムはどうしよう,
と考える.
hash 使うにしても少しは芸が必要である.
- 1735 研究所発.
床屋に行きたいんで,
さっさと退出する.
1746 東京モノレイル浜松町発.
外気温 25 ℃か.
昼間は暑かったんだ.
流通センターで降りて,
1815 第一京浜・環七交差点にある床屋.
三人待ち.
15 分ぐらい.
かなり髪を短くする.
所用時間 25 分.
髪を切ってもらいながら,
tree_name.pm での変換方法は
中間コードを介した hash を使うのがよかろう,
という結論を得る.
帰りに八百屋で野菜など買う.
1907 帰宅.
[近所の床屋]
値段 2100 円と安く回転も
それなりに速いので便利な
店ではある.「1500 円 15
分」というあの琴似の店に
はまだ及ばないが ……
- 帰宅して晩飯の準備してから,
ミルクティー飲むと眠くなる.
う,
いかん
……
と思いつつ 30 分ほど寝る.
- 晩飯食ってからも,
Perl による
怪しげなオブジェクト指向プログラミングらしきもの
は続く.
- すでに 0100.
まったく眠くない.
またかまたか.
- (一言近況)
9 月末までならば
「夏休み」とかいう
不思議なものを取ってよいことになってるんで,
来週末あたりから
夏休もうかなぁ
……
などと考えてます.
(20000906)
- 今日の食卓
- 朝 (0725):
昨晩の残り.
- 昼 (1220):
弁当.
昨晩の残りのマーボナスもどき.
- 晩 (2155):
昨晩の残りのナス.
なかなか減らん.
切り干しダイコンと
サツマイモの味噌汁
新しく作り直す.
だしは大きめのカタクチイワシの煮干.
それと干しシイタケ.