Powered by SmartDoc

コンピュータ

第二回
北海道大学理学部数学科

操作上の注意

一度入力した履歴はCtrl-p (CTRLキーとpを同時に押す)で前にたどり、Ctrl-nで後にたどれる。それぞれ、カーソルキーの上下でも同じ機能になる。Ctrl-kで行末まで削除、Ctrl-yで削除した文字列を貼り付けられる。

Ctrl-rを入力すれば、入力履歴を検索できる。

期待される処理時間よりも長く処理が終わらない場合、Ctrl-cで中断する。

条件分岐と繰り返し処理

for文

定型的な処理を繰り返す場合にはfor文を使う。正確には次の形式をとる。任意の配列を与え、先頭の要素からループ変数に代入される。

for ループ変数=配列
処理
...
endfor

具体的に、for文は以下の例のように使う。変数nを1から10まで1刻みで増加させ、配列xに代入している。これは繰り返し処理の基本的な構造である。

octave:8> for n=[1:10]
> x(n)=n
> endfor

つぎのように、増分を変化させることもできる。

octave> b=0;
octave> for a=[1:0.5:10]
> b=b+a
> endfor

if文

条件を与えて処理を変えるにはif文を使う。次の形式になる。

if(論理式)
真の場合の処理
endif

論理式の種類を表2.2.1[主な論理式(全て数値の比較)]に示す。

主な論理式(全て数値の比較)
相等 未満 以下 より大きい 以上 等しくない and or
== > >= < <= != && ||

複数の論理式のand,orを取るには( x == 3 ) && ( y != 4 )などと使う。

真偽に応じて処理を変えるには次の形になる。

if(論理式)
  真の場合の処理
else
  偽の場合の処理
endif

複数の論理式を扱うこともできる。elseifは複数回繰り返してもよい。

if(論理式1)
  論理式1が真の場合の処理
elseif(論理式2)
  論理式1が偽で論理式2が真の場合の処理
endif

if文によって次のような場合分けのある関数を記述できる。解析関数だけでは書けない関数を数値的に記述する場合、定義域を配列に格納し、各点に対応する関数値を別の配列に格納することになる。

octave:2> for n=[1:100]
> x(n)=n/100;
> if( x(n) < 1/2 )
>   y(n)=2*x(n);
> else
>   y(n)=2*x(n)-1;
> endif
> endfor
octave:3> plot(x,y)

浮動小数点値の比較には注意するべきである。次のようにexp( 2*pi*i)を計算してみれば、零であるべき虚数部分がそうはなっていない。これは特別なことではなく、計算機の数値精度が有限であることに由来する一般的な現象である。

octave:4> exp(2*pi*i)
ans = 1.0000e+00 - 2.4492e-16i

従って、整数値であることがわかりきっている場合を除き、if(x==0.0)という処理は避けることが望ましい。絶対値が十分に小さいことに置き換え、状況に応じてif( abs(x) < 1.0e-17 )などと記述する。

関数定義

新たな関数を定義することも可能である。同じ結果を、関数定義を利用して書いてみよう。言語によってはサブルーチンと呼ぶこともある。

octave:4> function y=f(x)
> if(x < 1/2)
> y=2*x;
> else
> y=2*x-1;
> endif
> endfunction
octave:5> for n=[1:100]
> x(n)=n/100;
> y(n)=f(x(n));
> endfor

functionからendfunctionまでが関数の定義である。冒頭のy=f(x)という記述において、fは関数名、xは関数の引数、yは返り値とよぶ。xに応じた値を関数ブロック内で変数yへ代入することで、fの値が決まる。

functionからendfunctionまでの関数ブロックに記述した変数は、関数ブロックの外部からは参照されない。これを局所変数と呼ぶ。関数内で局所変数を使えるために、関数の独立性が保たれる。

内容をどこからでも参照できる変数を大域変数と呼ぶ。大規模なプログラムでは大域変数の値を変更する点を特定することが困難になるため、なるべく使わないことが望ましい。

このように、関数を定義することで主要な処理の記述は簡潔になる。プログラムを記述する際には処理を関数に分割して書くべきである。

変数の保存

save文を使うことで変数値をファイルに保存できる。保存したファイルから読み込むにはload文である。

save "filename" 
load "filename"

三次元のグラフ描画

三次元のグラフ(要するに二変数関数のグラフ)描画にはplot3を使う。

octave> x=[1:100];
octave> y=[1:100];
octave> z=sin(x/10)' * cos(y/10);
octave> plot3(x,y,z)
z(x,y)=sin(x)*cos(y)のグラフ

行列演算sin(x)' * cos(y)を使ったが、for文を使えば次のようになる。行列演算の使える場合には行列演算を使った方がよい。

octave:1> for x=[1:100]
> for y=[1:100]
> z(x,y)=sin(x/10)*cos(y/10);
> endfor
> endfor
課題
1(復習):
行列M=[3,2; 2,3]の固有値を求める。
2:
例に挙げたz(x,y)=sin(x)'*cos(y)のグラフを、ベクトルの演算を使った手法とfor文を使った手法と、二通りで描画する。
3:
区間[0,1/2)ではx^3+(x-1/2)^5,[1/2,1]ではx^3+(x-1/2)^4で定まる関数をoctaveで定義する。定義域を0.1刻みで配列に与え、上の関数のグラフを描画する。

浮動小数点数の表現

計算機の表現できる数値は有限桁である。整数値は第一回に解説した通りであるが、実数値はどうであろうか。

もちろん無理数を表現できるわけではないので、適当な有理数として打ち切ることになる。64bitの倍精度浮動小数点数、32bitの単精度浮動小数点数とがあり、前者は精度の重要な科学技術計算に、後者は三次元グラフィクス(端的にいえばゲームなど)に利用されることが多い。

各bitは1bitの符号と仮数部、指数部に分けられる。倍精度であれば仮数部52bit,指数部11bitであり、単精度なら仮数部23bit,指数部8bitである。仮数部aは2進小数、指数部bは符号付き整数であり、という形になる。これを10進に変換して出力される。

処理装置によって、非零として扱える最小の浮動小数点数が決まっている。これを計算機イプシロンと呼ぶ。絶対値が計算機イプシロンを下回る数は0として扱われる。

octave:12> x=1.0e-324
x = 0
octave:13> x=1.0e-323
x =  9.8813e-324