この Notebook は,
テキスト「オープンソースソフトウェアによる情報リテラシー −第2版−」の
のプログラミング部分に相当する内容を JavaScript のかわりに Octave を使って書いてみたものです。
章番号はオリジナルの従来テキストに対応するように8章からはじめていますので,従来テキストを使用して授業を展開してきた教員や受講学生にも対応がわかりやすいかと思います。
また,テキストや授業と関係なく,初めて Jupyter Notebook で Octave を利用する学生や教員にとっても参考になるかも知れません。
この Notebook では,プログラミング言語としての共通部分に焦点を絞って解説します。
では,はじめましょう。
エンゲル係数とは,家計の消費支出に占める飲食費(食料費,食費)の割合(パーセント単位)です。
消費支出 100,000円,飲食費 40,000円の人のエンゲル係数を求める例。Octave では以下のような電卓的な使い方ですぐ答えが出ます。
本稿のように Jupyter Notebook 環境では,以下の1行を書いたあとに,Shift キーを押しながら Enter キー(または Return キー)を押して実行します。
40000/100000 * 100
ここからは,単に電卓的に使うだけではなく,応用・発展も見据えて以下のようなプログラム文を作成して実行することにします。
以下の例では,
s1
に消費支出である 100000
(円)という数値を代入し,s2
に飲食費である 40000
(円)という数値を代入し,x1
に代入し,x1
を表示させています。Octave では,文末に ;
をつけると結果が表示されません。
s1 = 100000;
s2 = 40000;
x1 = s2*100/s1;
disp(x1)
意に反して,プログラムがうまく動作しない場合があります。たとえば,上記の 3行目を以下のように書いた場合。
掛け算を示す演算子は *
,割り算を示す演算子は /
であるところを誤って,×
や ÷
と書くと,これらの記号は Python では演算子として定義されていないのでエラーとなります。このようなエラーは文法エラー(syntax error) と呼ばれ,Jupyter Notebook では,以下のように誤りやその箇所を指摘してくれます。
s1 = 100000;
s2 = 40000;
x1 = s2 × 100 ÷ s1;
disp(x1)
別の種類の誤りもあります。たとえば,「100」を「1000」と入力した場合...
s1 = 100000;
s2 = 40000;
x1 = s2*1000/s1;
disp(x1)
上記の例では syntax error (文法エラー) の警告が出ませんが,答えは明らかに変です。(エンゲル係数の最大値は100だから。)
このような場合はコンピュータにとって誤りではなく,指示通りに計算し,その結果を表示します。 このようなプログラム作成者の不注意や勘違いによって生じるエラーには注意が必要です。
プログラムが正しく動作しない場合は,誤りの箇所を探し,修正して再度動作を確認します。正しく動作するようになるまで,プログラムを修正し,実行(Shift + Enter)します。この作業をデバグといいます。
上記の例の 1行目では,s1
という名前の変数に 100000
という
数値を代入しています。変数名はアルファベットで始まる英数字列にします。大文字と小文字は区別されます。
変数 ss
に文字列を代入する場合は,以下のように "
(または '
)で囲みます。
ss = "エンゲル係数";
disp(ss)
掛け算を示す演算子は *
,割り算を示す演算子は /
。足し算は +
,引き算は -
です。
文字列の連結演算には strcat()
や cstrcat()
を使います。以下の例を参照。(strcat()
は末尾の空白を削除します。)
x0 = "エンゲル ";
y0 = "係数";
z0 = strcat(x0, y0);
z1 = cstrcat(x0, y0);
disp(z0)
disp(z1)
文字列と数値を直接連結することはできません。
s1 = 100000;
s2 = 40000;
x1 = s2*100/s1;
z1 = cstrcat("エンゲル係数は ", x1);
disp(z1)
そんなときは,num2str()
関数で数値を文字列に変換して連結します。
s1 = 100000;
s2 = 40000;
x1 = s2*100/s1;
z1 = cstrcat("エンゲル係数は ", num2str(x1));
disp(z1)
別解として,以下のように printf()
を利用して文字列と数値を並べて表示することもできます。
s1 = 100000;
s2 = 40000;
x1 = s2*100/s1;
printf("エンゲル係数は "), disp(x1)
printf()
は明示的に \n
で改行を指示しないかぎり改行しません。一方,disp()
は表示後,改行します。
以下は,書式設定の例です。%6.2f
は表示スペースを6桁分とり,小数点以下を2桁で表示します。
printf("エンゲル係数は %6.2f です。\n", x1)
2 + (50 - 5 * 6)/4
除算 /
は常に浮動小数点数を返します。 既定(format short
)では5桁表示ですが,fomat long g
などと指定すると15桁表示します。
17 / 3
format long g
17 / 3
累乗は **
または ^
です。
format short
2^4
2**4
s1 = input("消費支出? ");
s2 = input("飲食費? ");
x1 = s2*100/s1;
z1 = cstrcat("エンゲル係数は ", num2str(x1), " です。");
disp(z1)
(これまでの例では1回しか計算していませんが)よく使う計算を「関数」として定義する例です。
以下の例では,1行目から3行目でエンゲル係数を計算する関数 calc()
を定義し,7行目でその関数を呼び出しています。
%
から始まる行はコメント(実行に影響しない注釈)です。
function x = calc(s1, s2)
% 消費支出 s1 円と飲食費 s2 円からエンゲル係数を計算する。
x = s2*100/s1;
endfunction
format short
s1 = input("消費支出? ");
s2 = input("飲食費? ");
x1 = calc(s1, s2);
z1 = cstrcat("エンゲル係数は ", num2str(x1), " です。");
disp(z1)
いったん定義された関数は,以下のように何回でも利用できます。
calc(120000, 53000)
消費支出を入力すると,エンゲル係数が 20 ~ 40 となる飲食費を表示するプログラムをつくりなさい。
以下の例では,4行目で x
以下の最大の整数を与える関数 floor(x)
を使い,小数点以下を切り捨てたエンゲル係数の値を表示させています。(ちなみに,x
以上の最小の整数を与える関数は ceil(x)
です。)
また,エンゲル係数を計算する部分はすでに関数 calc()
として定義していますが,プログラム全体を関数 engel()
として定義してしまいます。
function engel()
s1 = input("消費支出? ");
s2 = input("飲食費? ");
x1 = floor(calc(s1, s2));
z1 = cstrcat("エンゲル係数は ", num2str(x1),
" です。(小数点以下切り捨て)");
disp(z1)
endfunction
engel()
小数点以下を切り上げたエンゲル係数の値を表示させるように上記のプログラムを変更しなさい。
Octave の組み込み関数に round()
と roundb()
があります。どちらも数値を丸める関数です。
以下の例からわかるように,小数点以下が 0.5
未満の場合と 0.5
を超える場合は,どちらも 四捨五入 と同様の丸め方ですが,ちょうど 0.5
のときは,round()
はいわゆる 四捨五入 で切り上げます。
一方,roundb()
の場合は,偶数に丸められていることがわかります。
これを偶数への丸めといい,端数が 0.5
より小さいなら切り捨て,端数が0.5
より大きいなら切り上げ,端数がちょうど 0.5
なら切り捨てと切り上げのうち結果が偶数となる方へ丸めます。
M1 = [12.49 12.50 12.51];
M2 = [13.49 13.50 13.51];
[round(M1), round(M2)]
[roundb(M1), roundb(M2)]
function engel()
s1 = input("消費支出? ");
s2 = input("飲食費? ");
x1 = calc(s1, s2);
if (x1 >= 80)
z1 = cstrcat("エンゲル係数は ", num2str(x1),
" です。飲食費を使いすぎです。");
else
z1 = cstrcat("エンゲル係数は ", num2str(x1), " です。");
endif
disp(z1)
endfunction
engel()
engel()
条件分岐の if
文の書式は以下のとおりです。
if (条件式1)
条件式1 が満たされた場合に実行する文
elseif (条件式2)
条件式2 が満たされた場合に実行する文
else
それ以外の場合に実行する文
endif
上記の条件分岐を,エンゲル係数が
と表示させるように変更しなさい。
s1 = 100000;
s2 = 40000;
z0 = cstrcat("消費支出 ", num2str(s1),
" 円に対するエンゲル係数の値");
disp(z0)
while (s2 <= 80000)
x1 = calc(s1, s2);
z1 = cstrcat(" 飲食費 ", num2str(s2),
" 円の場合: ", num2str(x1));
disp(z1)
s2 = s2 + 5000;
endwhile
s1 = 100000;
z0 = cstrcat("消費支出 ", num2str(s1),
" 円に対するエンゲル係数の値");
disp(z0)
for s2 = 40000:5000:80000
x1 = calc(s1, s2);
z1 = cstrcat(" 飲食費 ", num2str(s2),
" 円の場合: ", num2str(x1));
disp(z1)
endfor
for
文の書式は以下のとおりです。
for i = 開始値:増分:終端値
i が開始値以上,終端値以下の場合に実行される文
endfor
以下の値を求めるプログラムを作成せよ。
$$\sum_{n = 1}^{10} n^2$$上記の(練習)は,while
または for
を使った繰り返しの練習を想定しるが,Octave ではベクトルの要素毎の演算と sum()
を使って以下のように求めることができます。
x = [1:10] % 1 から 10 までの数値を成分にもつベクトル
x.**2 % ピリオド . をつけると要素毎に2乗する
sum([1:10].**2) % sum() は要素の和をとる