Powered by SmartDoc

コンピュータ

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

実習の内容

数学の学習に計算機とプログラムを利用できるようになることを目的とし、合わせて計算機の基本概念を習得する。

合否

毎回設定する課題の完了をTAあるいは担当教員が確認し、総合点で成績を決める。実習時間内の課題完了をもって出席とみなす。終わった後は自由に帰ってよい。

理由を問わず4回までの欠席を認める。教育実習、介護実習、教職関係科目による欠席も4回に含めるので、教職志望者は注意する。

欠席した回の課題を何もしなければ合格はしても成績は上がらない。別の実習日に確認を受ければ成績には反映することとする。

実習

プログラム言語としてoctaveを使う。数値解析用に開発されたフリーソフトウエアである。

起動と終了

octaveの起動と終了については授業で指示する。

算術演算

まず四則演算と冪乗を記述する演算子を使う。高級言語には剰余を与える演算子'%'が用意されているものだが、octaveには用意されていない。

冪乗
+ - * / **または^

算術演算の例を示す。

octave:1> (1+2-3*4)/5
ans = -1.8000
octave:2> 

初等関数

初等関数も用意されている。円周率としてpi,自然対数の底としてeなどは定数としてoctaveが定義している。

octave:2> sin(2)
ans = 0.90930
octave:3> cos(pi)
ans = -1
octave:4> exp(1)
ans = 2.7183
octave:5> exp(0)
ans = 1
octave:6> log(e)
ans = 1
octave:7> 4*atan(1)
ans = 3.1416
octave:8> asin(0)
ans = 0
octave:9> asin(1)
ans = 1.5708

変数と代入

変数への代入を利用する。変数名はoctaveのステートメントとして定義された予約語でなければよい。行末にセミコロンを付けると行の実行結果を表示しない。一般の高級言語と違い、変数宣言と型の指定は不要である。複素数もiを虚数単位として使える。変数は関数の引数としても使える。

変数への代入を使う例を示す。変数名をa,b,x,y,zとして、代入および演算を行う例である。

変数名には英数字とアンダースコアとを組み合わせて使う。大文字と小文字は区別される。

octaveが内部的に利用する変数はアンダースコアから始まる変数名をつけているので、通常使う変数名は英数字で始めるとよい。

octave:1> a=3
a = 3
octave:2> b=4
b = 4
octave:3> a*b
ans = 12
octave:4> x=3;
octave:5> y=5;
octave:6> z=x/y
z = 0.60000
octave:7> a**2
ans = 9
octave:8> a^2
ans = 9
octave:9>  z=1+i
z = 1 + 1i
octave:10> z*i
ans = -1 + 1i
octave:11> a1=3
a1 = 3
octave:12> a2=4
a2 = 4
octave:13> a_value=3
a_value = 3
octave:14> b_value=4
b_value = 4

以上の内容を理解すれば、少なくとも電卓としてoctaveを利用できるはずである。

配列

同時に複数の変数を定義する場合、a1からa10などと変数名を与えても煩雑であり、融通が利かない。そのような場合には配列という形で定義する。

配列名をxとしよう。x=[0:10]と実行してx(1)からx(11)までの11個の変数を同時に与えることができる。

配列変数の定義
octave:1> x=[0:10]
x =
   0   1   2   3   4   5   6   7   8   9  10
octave:2> x(1)
ans = 0
octave:3> x(2)
ans = 1
octave:4> x(3)
ans = 2
octave:5> x(11)
ans = 10
octave:6> x(4)
ans = 3
octave:7> x(6)
ans = 5
octave:8> x(1)=20
x =
  20   1   2   3   4   5   6   7   8   9  10

各x(k) (1 <= k <= 11)を配列xの要素とよぶ。kを配列の添字とよぶ。次のように、添字には変数を与えてもよい。

octave:9> a=3
a = 3
octave:10> x(a)
ans = 2

配列とグラフ描画

整数値のみの配列変数では不便である。要素ごとに代入してもよいが、初期化する方法がある。

配列をx=[0:.1:10]と定義して配列変数値を0.1刻みに与えることができる。

これを利用して、初等関数のグラフを描こう。次の例では、変数としてx(1)からx(32)までが与えられたことになる。グラフ描画にはplotステートメントを用いる。plot(配列,関数)という形になる。

解析関数であればsin(x)という形式でx(n)の各成分にsinを作用した値を得るが、多項式では配列の各成分を明示的に処理するため、.*という演算子を用いる。算術演算子にピリオドを付加した演算子が配列成分ごとの演算子として用意されている。

実習
octave:8> x=[0:.1:pi]
x =
 Columns 1 through 8:
0.00000 0.10000 0.20000 0.30000 0.40000 0.50000 0.60000 0.70000
 Columns 9 through 16:
0.80000 0.90000 1.00000 1.10000 1.20000 1.30000 1.40000 1.50000
 Columns 17 through 24:
1.60000 1.70000 1.80000 1.90000 2.00000 2.10000 2.20000 2.30000
 Columns 25 through 32:
2.40000 2.50000 2.60000 2.70000 2.80000 2.90000 3.00000 3.10000
octave:9> plot(x)
octave:10> plot(x,sin(x))
octave:11> x=[0:.1:2*pi];
octave:12> plot(x,sin(x),x,cos(x))
octave:12> plot(x, x .* x )
plot(x,sin(x))による三角関数のグラフ描画結果

行列とベクトルの扱い

行列もベクトルも配列として扱う。ベクトルは配列そのものである。配列は横ベクトルとして扱われることに注意する。配列xを縦ベクトルとして扱うにはシングルクオートを用いx'とする。

行列は多次元の配列として扱う。行ごとにセミコロン;で区切る。加算、減算、乗算、除算はそのままである。積は行数と列数の対応に注意する。除算は正則性に注意する。

次に配列の成分ごとの定義と行列の定義を与えた。

octave:1> x=[1,3]
x =
  1  3
octave:2> M=[2,1; 1,2]
M =
  2  1
  1  2
octave:3> M * x
error: operator *: nonconformant arguments (op1 is 2x2, op2 is \
    1x2)
error: evaluating assignment expression near line 3, column 3
octave:3> M * x'
ans =
  5
  7
octave:4> x * M
ans =
  5  7
octave:5> inv(M)
ans =
   0.66667  -0.33333
  -0.33333   0.66667

行列のi,j成分はM(i,j)として参照する。成分ごとの演算は演算子の前に.を付加し、.+, .-, .*, ./という演算子を使う。

octave> M=[1,3;2,5]
M =
  1  3
  2  5
octave> M .* M
ans =
   1   9
   4  25
octave> M(2,2)
ans = 5

固有値と固有ベクトル

行列とくれば固有値である。eig()は行列を引数にとる関数である。結果は縦ベクトルとして返ってくる。

octave:6> eig(M)
ans =
  1
  3
octave:7> 

固有ベクトルを求めるには次のように配列への代入という形をとる。Dに固有値が対角に代入され、vには対応する固有ベクトルが代入される。

octave:7> [v,D]=eig(M)

重複固有値の場合

重複固有値の場合はどうだろうか。2次の標準型で確認する。固有ベクトルは求められるが、この場合は一般化固有空間を張る基底をもう一次元だけ見つけなければならない。

octave:1> M=[2,1;0,2]
M =

  2  1
  0  2

octave:2> [v,D]=eig(M)
v =
   1.00000  -1.00000
   0.00000   0.00000

D =
  2  0
  0  2

octave:3>

上記の場合、で定まる固有ベクトルxについて、を満たすyが存在する。x,yの組は一般化固有空間の基底になっている。

以下、3次行列の場合を考える。次の例では固有値2が重複している。一般化固有空間の次元はvのランクから判断することになる。ランクを求めるにはrankを使う。

octave:1> A=[2,1,0;0,2,0;0,0,3]
A =
  2  1  0
  0  2  0
  0  0  3
octave:3> [v,D]=eig(A)
v =
   1.00000  -1.00000   0.00000
   0.00000   0.00000   0.00000
   0.00000   0.00000   1.00000

D =
  2  0  0
  0  2  0
  0  0  3

octave> A=[1,3,-2; -3,13,-7;-5,19,-10]
A =

    1    3   -2
   -3   13   -7
   -5   19  -10

octave> rank(A)
ans = 3
octave> E=[1,0,0;0,1,0;0,0,1]
E =

  1  0  0
  0  1  0
  0  0  1

octave> rank(A-2*E)
ans = 2

同様に、3重解の場合の標準型の一つを見る。vのランクに注意する。この場合、固有ベクトルxについてを満たすyが存在する。

octave:1> A=[2,1,0;0,2,1;0,0,2]
A =
  2  1  0
  0  2  1
  0  0  2

octave:2> [v,D]=eig(A)
v =
   1.00000  -1.00000   1.00000
   0.00000   0.00000  -0.00000
   0.00000   0.00000   0.00000
D =
  2  0  0
  0  2  0
  0  0  2

octave> A=[3,-3,-1;3,-4,-2;-4,7,4]
A =

   3  -3  -1
   3  -4  -2
  -4   7   4

octave> rank(A)
ans = 3
課題
  1. 節[実習]の実習例を実際に実行する。各行が何を意味しているか、答えること。
  2. 二次行列M=[1,1;1,2]について、eig(M)を用いて固有値、固有ベクトルを求める。
  3. 固有値が重複している二次行列M=[5,1;-1,3]について、その固有値をeig(M)で求める。
  4. 固有値が三重に重複している三次行列A=[3,-3,-1;3,-4,-2;-4,7,4]についてeig(M)で固有値を求める。固有値を手計算し、結果を確認する。

背景知識

計算機の数値表現

デジタル型の計算機では数値表現に二進数を使う。電位が0Vから規定の電圧以下の場合を"0"と定め、規定の電圧以上の場合を"1"と定める。二進数4桁を16進数1桁で表現することが多い。

二進数1桁を1 bit, 8 bitを1 byteと表記する。$2^10=1024$ bit (byte)で1 K bit (byte)とよぶ。1024 K bitが1 M bit, 1024 M bitが1 G bitである。

正の整数値は二進数をそのまま使えばよい。負の整数値を扱うには工夫が必要である。整数値として扱うbit数は処理系によって異なるが、ここでは4bitで与えておこう。一般には32bitである。

4bitで5を表示すると0101になる。-5は5との加算で0になる数であるから1010+1=1011となる。ここで1010は0101をbit毎に反転させたものに他ならない。このような表記を2の補数表示という。

加算、減算は同様である。二進数の場合、乗算はbitごとのシフトによって与えられる。これはデジタル型の計算機がアナログ型の計算機を凌いだ理由の一つである。

処理装置の処理単位を基準に整数値のbit数を決めることが多い。32 bit CPUであれば整数値を32 bitで処理することが普通である。

計算機の記憶域は有限なので、実数値とくに無理数値をそのまま扱うことはできない。一般には浮動小数点数として扱うことになる。仮数部と指数部の積として表現する。仮数部は絶対値1未満0.1以上の規定精度小数として、指数部は2の冪乗で与えられる。

計算機を使うということ

計算機を使うといった場合に期待される能力は二つに分けられる。一つは必要なアプリケーションプログラムを探し出して利用する能力、もう一つは必要なアプリケーションを設計しプログラムとして作成する能力である。

少なくとも理系の大学卒業者に期待される能力は後者であるが、数学科では十分な実習時間を取れないため、内容を非常に限定したものとしている。

求人先はコンピュータ関連事業を営む企業が多い。卒業後の進路も同様である。そこで必要とされている能力を捉え違えてはいけない。

理想的には高級言語としてC, C++, Pascal, FORTRAN, Java等を実際に使い、Mathematica, Maple, MATLAB, octave等を数式処理系として補助的に使えるようになり、Perl, Rubyなどのスクリプト言語を事態に応じて利用できるという能力を持つことが望ましい。欲をいえば言語設計までできるとよいのだが、そこまでやるには情報工学科程度のカリキュラムが必要である。

高級言語の要件

プログラムを作成する手段は多い。

最も原始的な手段は処理装置ごとに定義された機械語(アセンブリ言語を含めて機械語と呼ぶことにする)によって記述するものである。家電など機能が制限された組込系のプログラムには用いられる可能性がある。また、応答速度が問題になる処理には特にサブルーチンを機械語で書く場合がある。

機械語は処理装置に依存するため、処理装置に依存しないプログラム言語の規格が考案され、それを実装した言語処理系が普及してきた。例えばFORTRAN77という規格に沿った実装の一つがGNUのg77処理系であり、BASICという規格に沿った実装の一つがPC9801に搭載されていたN88 BASICであるなどである。

高級言語に必要な要件には、変数宣言、算術演算子、論理演算子、制御構造、サブルーチンの存在などがある。これらを知っていれば新しい高級言語を利用する場合にもとまどうことはなく、それぞれの概念がどのように実現されているのかを調べるだけでよい。重要な点は解決するべき問題、作成するべきプログラムに応じて適切な言語を選択することである。実習で使うoctaveは一つの例に過ぎない。

現在の計算機は基本的にノイマンマシンである。処理装置とアドレス付けされたメモリから構成され、メモリに格納されたプログラムをアドレス順に逐次実行するものである。処理するべきデータは数値としてメモリに格納され、基本的に格納されているアドレスによって参照される。

データの入出力には処理装置に応じた手段が用いられ、記憶装置の一部として扱う場合と入出力専用に独立したアドレス系列を用いる場合とがある。

コンパイラとインタプリタ

高級言語の実装にはコンパイラによる実装とインタプリタによる実装とがある。コンパイラによる実装とは高級言語のソースプログラムを機械語に変換した実行形式を生成するものであり、インタプリタによる実装とはソースプログラムを一行毎に機械語へ変換しながら実行するものである。コンパイラの典型はGNUのC言語の実装であるgccであり、インタプリタの典型はJava言語の多くの実装である。octaveはインタプリタである。