暇な理系大学生の備忘録

ちょっとしたことをつらつらと

乱数生成法について

こないだちょっとCでプログラムを書いているときに乱数生成について少し調べたりしたのでメモ書きを...

 

基本的には大体のプログラミング言語には乱数生成の関数が標準ライブラリに組み込まれています。

たとえばC言語ならrand()関数。

 

しかし、ちょっとした理由からrand()関数が使用できない制約の上で乱数を使用する必要がある状況に出くわしました。

 

そうなると自分で乱数生成関数を用意しなければなりませんが、

僕は別段そういった方面の数学的知識はありませんので乱数生成アルゴリズムについて調べました。

 

見つけた中で簡単に実装できるものが2つ見つかりました。

 

1.線形合同法

2.XorShift法

 

です。

 

C言語のrand関数は1の線形合同法を利用したもの(だったはず)です。

実際の実装方法はたしかwikiに載っていたものを使いました。

 



unsigned long sen_gou(){

static unsigned long x = 10;

unsigned long a = 1103515245, c = 12345, m = xx(2, 31);

x = (a*x + c) % m;

return x;

}

xx関数は第一引数を第二引数乗するべき乗関数です。

本来ならpow関数(?)だったかmath.hあたりをインクルードすれば使えた気もしますが、math.hも使えない制約があったので作りました(記述するのは省略)。

 

sen_gouが線形合同法による乱数生成関数です。

これで吐き出された数字をModしてやれば任意の範囲での乱数が得られます。

%6+1して1~6で、 % 10+1して1~10の範囲で乱数を求め、また総計算回数の大小おけるそれぞれの値の出現数を可視化してみました。

横軸がそれぞれ生成した値、縦軸がその値の出現数です。

f:id:hima_b:20170524150715p:plainf:id:hima_b:20170524150740p:plain

 

もう一つのXorShift法の実装コードも確かwikiにのっていたはずです。

 



unsigned long xor128(){

	static unsigned long x = 123456789, y = 362436069, z = 521288629, w = 88675123;

	unsigned long t;

	t = (x ^ (x << 11)); x = y; y = z; z = w; return(w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)));

}

 で、これも先ほど同様に実行回数と出現数の可視化をしました。

f:id:hima_b:20170524151630p:plain

f:id:hima_b:20170524151701p:plain

 

今回は乱数の生成結果をModして任意の範囲で取り出したので、元の生成結果の傾向がどうとかは判断できませんでしたが、(そこを論じれるほど理解していないので)、まぁこれでrand関数なしでも乱数が生成できることはわかりましたね。

 

もし、時間変数やタイマーを用いれる環境であれば、その値を用いて2種類の生成法を不規則に呼び出してやれば面白いかもしれません。

 

x,yは任意の値として

timer%x > yなら

a = sen_gou();

そうでないなら

a = xor128();

のような感じで。

 

ほかにもいろいろな乱数生成法はありますし、それに関する論文を書かれている方も多くいらっしゃるので、興味がある方は読んでみるのもいいかもしれません。

 

では。

 

 

 

 

gnuplotの使い方【応用編】

今回はy、もしくはx軸を共有したグラフの書き方を記したいと思います。

 

具体的にはこんな感じ

f:id:hima_b:20170506213825p:plain

複数の出力、測定結果を比較する際、

ディジタル波形などの比較などの際には有効に活用できると思います。

 

まずはスクリプト全文を載せます。

gnuplotスクリプトとは?という方は前回記事を見てください。

 

hima-b.hatenablog.jp

 


set multiplot layout 4,1
set datafile separator ","

set lmargin 0
set rmargin 0
set tmargin 0
set bmargin 0

set ytics 1
set xtics nomirror
set ytics nomirror

set xr[0:3e-4]
set yr[-0.2:1.2]

set size 0.8,0.20
set origin 0.1, 0.70
unset xlabel
unset ylabel
unset xtics
plot 'data.csv' using 1:2 with line linecolor -1 title 'ClockPulse'

set size 0.8,0.20
set origin 0.1, 0.50
unset xlabel
unset ylabel
unset xtics
plot 'data.csv' using 1:3 with line linecolor -1 title 'X0'

set size 0.8,0.20
set origin 0.1, 0.30
unset xlabel
unset ylabel
unset xtics
set ylabel '[V]'
plot 'data.csv' using 1:4 with line linecolor -1 title 'X1'

set size 0.8,0.20
set origin 0.1, 0.10
set xlabel 'time [s]'
unset ylabel
set xtics
set xtics nomirror
plot 'data.csv' using 1:5 with line linecolor -1 title 'X2'

unset multiplot
    

 まず最初、multiplotは縦に4つ、横に1つ表示する宣言になります。

それのペア的存在として最後にはunset multiplotと書きます。

その次のset ○margin 0というのはleft,right,top,bottomそれぞれの余白(グラフの枠の外)の幅の指定です。

すべて0にしておくとそれ以降のグラフが書きやすいので今回は0にしています。

 

ticsや描画範囲については過去の記事を。

 

set sizeはそのグラフ"1つ当たりの"大きさの指定です。"グラフ全体の"横と縦を1、1としたときの比率で指定します。

set originはその"グラフ1つの左下の座標"の場所を指定します。基準は"グラフ全体の"左下の座標を0,0としています。

 

あとは一つ一つグラフの設定を書いていけばok

一番下のx軸だけ表示して、それ以外は非表示にしています。

(x軸は共通なので)

もし共通幅のx軸でなくてもこのようなレイアウトでグラフを作成することはできます。

上のグラフは大きさ比率0.5、下のグラフの大きさ比率0.8のようなイレギュラーなグラフを作ることも可能ではあります。大きさや座標が指定できるので割と何でもできると思います。

一つのキャンパスに複数の絵を飾る感覚ですね。

 

例えば応用すればこういうのもできます。

f:id:hima_b:20170506221026p:plain

log(x)+1のグラフをxが1~10の範囲は線形表示、それ以降は対数表示というようなグラフも書けます。使い道があるかはわかりませんが...

 

今回はここらへんで。

 

 

gnuplotの使い方【基本操作編(ちょい足し)】

レポートを書いてる中で少し使い方を記しておきたいことが出てきたので書きたいと思います。

 

今回の内容はgnuplotスクリプト、pltファイルの書き方です。

 

書き方と言っても簡単で、内容としては今までのコマンドとさほど変わりません。

何が良いかというとスクリプトファイルに実行したいコマンドをすべて書いておいて、それを一括で実行できる点にあります。

 

特に次の記事で書こうと思っている複数のグラフを一つの描画に収める作業をする際には10や20のコマンドを書くことになるので重宝します。

 

そのスクリプトの書き方は適当なテキストエディター、メモ帳なりEmEditorを開いて実行したいコマンドを順にgnuplotに直で書いてるときと同じように記述します。

 

 こんな感じ

f:id:hima_b:20170506192252p:plain

data.csvっていうのはこんなの

f:id:hima_b:20170506192320p:plain

 

これをgnuplotのbinファイルにほりこんでやって

gnuplot

load "sc.plt"

 

と実行してやればok

f:id:hima_b:20170506192654p:plain

sc.pltの部分は各々作成したスクリプト名に変更してください。

 

今回しれっと書いた

set xtics nomirror
set ytics nomirror

 はx軸やy軸の目盛を上や右に写さないコマンドです。

ちなみに軸の目盛事体を消す場合は

unset xtics

目盛幅を任意の数にするときは(例えば3なら)

set xtics 3

 という風に書きます。

 

では次の記事では複数のグラフを(x軸またはy軸を共有して)同時に出力する方法を書きたいと思っています。

 

では。

gnuplotの使い方【おまけ編】

 

前記事で書いたようにこの記事では理系のレポートにできるだけ適した

フォーマットにグラフを近づけるようにするコマンドをいくつか紹介したいと思います。

 

まず1つ目、グラフの線をカラーではなく黒にする。

レポート用に使用するグラフにカラフルなものはあまり好まれません。

なのでこのコマンド

plot 'data.csv' using 1:2 with line linecolor -1

 以前紹介したCSVファイルを1列目と2列目を使用し、線で結んで表示

するコマンドに付け加えたlinecolor -1が今回のコマンドです。

 

その名の通り線の色を指定しています。数字の部分は色が割り当てられています。

(黒が-1なのでそれ以外の色の数字は覚えていませんが試してみてください)

 

2つ目、軸ラベルの編集

こんな感じ

set xlabel 'x'
set ylabel 'x^2'
replot

 ''の中身がラベル名になりますが、ここでポイント。

^の後ろに文字を書くと上付き文字

_の後ろに文字を書くと下付き文字にできるので

指数や添え字を書くときに使ってみてください。

例 : ㎡を書くときはm^2

 

3つ目、凡例の編集

凡例はデフォルトだとplot以降のコマンド(data.csv using 1:3)みたいなのが

表示されますがこれを任意の名前にするには

plot 'data.csv' using 1:3 with line linecolor -1 title 'f(x)'

 といった風に書きます。長くなりましたね(笑)

 

title 'f(x)'の部分で凡例名を指定しています。''の中がその凡例名ですね。

 

また、凡例を表示する必要がないときは

unset key

 で消せます。

 

以上のようなコマンドを用いると

f:id:hima_b:20170420212611p:plain

こんな感じのグラフが描けます。

それっぽくなったでしょ?(笑)

 

あとはレポート上に張り付けるだけ。(もちろんこれを張った下には図の名称を書きましょうね)

 

今回紹介した以外にもgnuplotにはいろいろな機能があります。

(正直なところここで述べたことなんて米粒程度にも満たない)

 

ので、知りたい人は調べてみてください。

 

長々と数記事にわたりましたが以上です。

(またそのうちほかの機能について書くこともあるかも?)

 

では。

 

 

gnuplotの使い方【CSVファイル使用編】

 

やっとCSVファイルのデータの可視化、グラフ化のための

グラフ描画ソフト(gnuplot)の使い方の説明をします(笑)

前記事で思いのほか長くなったので分割しました。

 

f:id:hima_b:20170420204005p:plain

 

今回使用したCSVファイルは上のようなもの(参考までに)

左がExcelで表示、右がEmEditorで表示したものです。

 

1列目がxの値とすると

2列目 : y = x

3列目 : y = x^2

4列目 : y = sin(x)

となっています。

ちなみに関係ありませんが思い出したので一つ、円周率πはgnuplotではpiと書けば使えます。(例 : pi*sin(x))

 

さて、このCSVgnuplotのプログラムがある場所にあるフォルダbinの中にほり込みます。※

別にどこの場所にCSVファイルがあっても大丈夫ですが、binフォルダの中に入れておくと書くコマンドが簡単なのでそうすることをお勧めします。

 

gnuplotを起動し

 

set datafile separator ","

plot 'data.csv' using 1:2

 

と入力し実行します。

 

この意味としては一行目はCSVファイルが何で区切られているかの宣言になります。

基本的にはカンマで区切られているはずなのでこのままでいいのですが、

たまーに / やら : やらで区切られている場合があるかもしれません。

そのときは""の中をカンマからそれらに変えれば大丈夫です。

 

二行目は

plot 'ファイル名' using (x軸に何列目のデータを使うか):(y軸に何列目のデータを使うか)

といった構成になっています。

 

1列目をx軸に、4列目をy軸に使いたければ using 1:4に変更すればOK。

 

using 1:2で表示したら以下の通り

f:id:hima_b:20170420210039p:plain

 

点々じゃなく線でつなぎたいときは

plot 'data.csv' using 1:2 with line

 と書く。

 

するとこんな感じ

f:id:hima_b:20170420210224p:plain

 

と、前回の基本操作編と合わせればCSVファイルを可視化することは

できるようになったと思います。

 

ただ、これでもまだ理系のレポート、論文に適したフォーマットとは言い難いので、

一応この次におまけ編でそこら辺のフォーマット編集コマンドについて簡単に

書いておきたいと思います。

 

レポート作成などでgnuplotを使おうかと思ってる人はそちらを読んでみてください。

 

では。

 

※追記(2017/6/22)

私の環境では非インストールタイプのgnuplotを使っているためカレントディレクトリがbinでしたが、インストールタイプを含め環境によってはそのかぎりではないようなので、各自のカレントディレクトリ直下にcsvファイルを置いて頂ければ問題ありません。 

 

gnuplotの使い方【基本操作編】

 

前回

 

hima-b.hatenablog.jp

 

こちらでgnuplotで扱うCSVファイルについて簡単にちょっと

書きましたが、肝心のグラフ描画ソフトについての話はしていませんでした。

 

今回説明するグラフ描画ソフトはgnuplotというものです。

入手方法についてですがwindows版については適当にぐぐったら出てきます。

mac版ですがどっかしらで入手できますが、一番手っ取り早いのは

数学計算ソフトのMaximaをダウンロードするとついてきたはずです(たぶん)

Linux版についてはごめんなさい、Linux自体ほぼ触らないのでわかりません。

 

なぜgnuplotかというとたまたま何かでこれを知り、使い方も簡単でwin、mac版ともにあり、シンプルでよかったというだけのことです。

好みみたいなところが大きいですが、グラフ描画ソフトを探している人は

触ってみるといいと思います。

 

グラフ描画に関してはgnuplotのほかにPythonというプログラミング言語

そのライブラリmatplotlibを用いることも多々ありますが、それに関しては

また今度。

 

ではgnuplotの基本的な使い方から

gnuplotを起動するとこんな感じのコマンドプロンプト(ないしはターミナル)

が起動すると思います。

f:id:hima_b:20170420195418p:plain

 

これがgnuplotの操作画面です。

初めに言っておきますが終了する際は×ボタンではなくexitと打ってエンターを

押してくださいね。(でないとエラー吹いたりするので)

 

起動したら早速動かしてみましょう

 

plot sin(x)

 と入力し実行すると

f:id:hima_b:20170420200346p:plain

この通り

 

読んで字のごとくsin(x)をプロットしたわけです。

gnuplotでは

 

三角関数

sin(x), cos(x), tan(x)

対数、指数

log(x), exp(x)

ルート

sqrt(x)

 

などが使えます。他にもいろいろな関数がサポートされてたと思うので

気になる方はぐぐってね。(そのうち書くかも)

 

四則演算は

+,-,*,/

の通りです、多くのプログラミング言語と似ています。

累乗は **というふうに掛け算のアスタリスクを二つであらわされます。

 

例. xの二乗

x**2

 

さて、xの範囲を変えたい、と思いませんでしたか?(思いましたよね)

 

範囲の指定は

set xr [-5:5]
set yr [-1.5:1.5]
replot

 といった感じです。

 

上から順に

x(横軸)の表示範囲指定

y(縦軸)の表示範囲指定

再描画

を意味しています。

 

何か表示の設定を変更した際はreplotしないと更新されません。

 

また複数の数式を同時に表示したい際は

plot sin(x),cos(x)

 といった風にカンマで区切ればいいだけです。

 

媒介変数表示したいときは

set parametric
plot cos(t),sin(t)

 と書きます。

 

一行目が媒介変数表示モードを使う宣言みたいなものです。

gnuplotを終了するともとに戻るので使うときに書いてください。

二行目のplotの後は先ほどの複数の数式の同時表示と似ていますが、

plot (xの媒介変数表示), (yの媒介変数表示)

となっています。tが媒介変数にあたります。

 

これで一般的なグラフの描画はできるようになったと思います。

 

グラフデータはツールバー左から二番目のドライブに矢印が入ってるアイコン

(カーソルを合わせるとexport plot to fileとか表示されたはず)

を選択すると、pdfとかpngで保存できるので適宜使用してください。

 

と、ながながと書きましたがCSVを扱う方法をまだ書いていません(笑)

 

長くなったので次の記事分けますね。

 

CSVファイルについて【gnuplotを使う前に】

 

理系大学生なら基礎、専門問わず実験をすることが多々あると思いますが

よく言われることが

 

「グラフはExcelを用いないこと」

 

というのもExcelはあくまで表計算ソフトであり、理系のレポートや

論文を書く際の体裁に適していないということがあげられます。

(設定をきちんと整えればその限りでない)

 

そんな時、仕方なくほかに使えそうなグラフ描画ソフトを探して

使うと思いますが、いずれの場合も実験によって得られたデータを

ソフトに渡す際に用いられるファイル形式があります。

(特にオシロスコープなどの測定機器からデータを出力したときは

CSVがよく用いられる)

 

今回はそのファイル形式CSVファイルについて簡単にご紹介したいと思います。

 

そもそもCSVとは何か、どんなものかという話になりますが

簡単に言えばカンマなりなんなりの記号でデータが区切られた

テキストデータみたいなものです。

 

 こんな感じ

f:id:hima_b:20170420185002p:plain

これはカンマで区切られたCSVEmEditorで開いた時の様子です。

 

ただ、これだとわかりにくいのでCSVを編集する際などはExcelLibreOfficeのCalc(だったかな?)などを使うことが多いです。

 

どこの値が何を意味してるかというと、一番左の値における何らかの測定値、理論値などがその右に順に連なっているわけですが、数学的に表すと、

 

t, f(t), g(t), h(t), ...

 

といった感じですね。

そのセットがt=1のとき2のとき...といった風に下に続いていると思ってもらったら

分かりやすいかもしれません。

 

当たり前のことですが、1列目に5つの要素があれば2列目にもn列目にも5つの要素があります。

f:id:hima_b:20170420185918p:plain

このようにでこぼこになることはありません。(値が"空"としてのデータの場合はあるかもしれませんが...)

 

基本的に要素の数が異なるCSVをグラフ描画ソフトに読み込ませるとエラーを吹くことが多いです。

 

また、CSVは何も測定機器が出力する以外にも自分で作成することもできます。

Excelなど表計算ソフトで作成し、保存する際に.CSV(カンマ区切り)

などを選択すればよいだけです。

 

ここで注意すべきはCSVはテキストデータなのでExcelなどで編集していた際は

数式やグラフなどを書いたとしてもCSVファイルには保存されません。

(数式は計算結果の値として保存されますが、グラフやセルの塗りつぶし、色、フォントの情報などはなくなります)

 

作業の途中でグラフなどを書いていたり、計算式を残しておきたい場合は別に

.xlsxなどで保存しておきましょう。

 

ここまでCSVってどんな感じのものなのかなんとなく説明してきましたが、

肝心のCSVをどうやってグラフ化するのかを説明していませんでした。

 

これに関しては別の記事で書きたいと思います。

(正確にはその記事の前置きにこの記事を書きました)