計算機言語 I 第 8 回 関数 ( その 2)
この資料: http://www.math.u-ryukyu.ac.jp/~suga/gengo/2022/08.pdf
Firefox の cache( キャッシュ ) のクリア
情報基盤統括センターでは, 各個人が作成できるファイルの総量を規制してます(Disk quota あるいは
Storage quotaという). センターが用意できる2次記憶装置の容量に限りがあるので, それを, 使用者全員で
分け合わなければならないからです.
ソフトウェアには,動作の途中でファイルを保存していくものがあります.Firefoxのようなウェブブラウ ザでは,アクセスしたWeb サイトのデータ(html ファイルや画像ファイル)を cache(キャッシュ)という形 で保存しています.例えば,「戻る」というボタンがウェブブラウザにありますが,戻るボタンが押された際に は,ネットのデータにアクセスするより,キャッシュにあるデータにアクセスします. ネットからデータを読む より,ディスクデータにアクセスする方が,遥かに速くデータが得られるからです
このウェブブラウザのキャッシュのせいで,上で述べた個人のDisk quota を越えるという現象が起きてい るようです. Geditで「ファイルが保存できない」とのメッセージが出た場合, Disk quotaの制限のためです. 次の手順で, Firefoxのキャッシュを消去して下さい.
1. Firefoxを起動する.
2. Firefoxの上部右側(URLを入力する欄があるところの右端)のメニューボタンをクリック
3. 現れるメニューから「設定」を選ぶ.
4. 左側の「プライバシーとセキュリティ」欄を選ぶ.
5. 中心となるウィンドウの中の「Cookieとサイトデータ」のところにある,「データを消去」ボタンを押 す.(これでキャッシュデータの消去ができます.)
6. 次の Firefoxを閉じたときに Cookieとサイトデータを消去するにチェックを入れておくと, Firefox
が原因で, Disk quotaが問題になることは無くなります.
レポートへのツッコミ
レポート問題では, ヘロンの公式を利用した関数を書いていただきましたが,エラー処理は,「面積の値とし てはあり得ない, 0以下の数を返す」ということで実現する仕様にしたわけです.
他にも関数設計の考え方はあり,例えばエラー処理を平方根を取る関数sqrtに任せるというのも, ひとつ の考え方です. ちなみに, 数学関数ライブラリのsqrt 関数は, 負の値を受け取ったときには, NaN (Not a
Number, double型の値として定義されている)という値を返します.
レポート問題に対する私が考えた模範解答は, 次です. 下のプログラムでは, Sは3角形を成さない正の 3 つの数を入力すると, 0以下になること(証明は各自考えること)を利用しています.
「return文があると,そこで関数は値を返して処理を終了する」は覚えておいて下さい. double heron(double a, double b, double c)
{
double s, S;
if ( a<=0 || b<=0 || c<=0){/* 辺の長さは正 */
return 0.0;
}
s=(a+b+c)/2.0;
S=s*(s-a)*(s-b)*(s-c);
if (S <=0) { /* このとき 3角形にならない */
return S;
}
else { /* 面積は, S の平方根 */
return sqrt(S);
} }
レポートに対するツッコミですが,
• 3角不等式を間違えているものがありました.
• 3角不等式でエラーチェックするには, 3通りのチェックが必要です.
• sqrt に負の数を入力してしまうプログラムがありました. これでは, 私が提示した仕様にはなりま せん.
• 辺の値が負の数になったときにチェックをした人は,少数でした.
教科書 6.4 節の補足
「Cの関数の引数は値渡し」は,いわゆる「構造化プログラミング」を実現するための言語仕様です. ただし, 値渡しだけでプログラムを書くのは,効率性を犠牲にすることもあるので, ポインタを利用した参照渡しも可 能にしてあるのです. このあたりの詳しい考え方は,次回のポインタの時に解説します.
教科書 p.92, 6.6 節の補足
ヘッダ(header)ファイルに対する解説がありますが,少し補足しておきます.
#includeは,cpp(Cプリプロセッサ)への指示で,そのあとに続くファイルの内容をプログラムソースに取 り込みます. ほとんどの場合,教科書にあるようにヘッダファイルと呼ばれるものを取り込みますが,それ以外 のファイルを取り込まないわけではありません. C のソースファイルを取り込んでも構わないし,プログラム で利用するデータを取り込んでも構わないのです.
この講義で利用しているstdio.h,math.hはヘッダファイルと呼ばれます. 多くの場合,ヘッダファイルに は,次の2つを記述します.
• cppのマクロ置換を利用した定数の定義
• プログラムソースに記述する関数のプロトタイプ宣言
大きなプログラムの作成では,ヘッダファイルに上のような関数のプロトタイプと定数定義を記述し,プロ グラムソース(hogehoge.c)は,「関数の実装」を書くようにすることが多いようです. このようにすることで, ヘッダファイルを読むだけで,どのようなプログラムを作成しているかの概要がわかるからです.
教科書 p.93, 6.7 節 , 再帰 (recursion) の補足
再帰とは, 関数の処理の途中で自分自身を関数呼び出しすることです. 再び自分自身に帰ってくるので再帰 と呼ばれます.
計算機概論Iのmapleの講義の回で,再帰の話を1度しました. その際にも述べたことですが,再帰の利点, 欠点は次になります.
• プログラムの記述が簡潔で分かりやすく(読みやすく)なる.
• 関数呼び出しの度にスタック領域と呼ばれるメモリを消費するので,処理によってはメモリが足りなく なる.
• 関数呼び出しという動作が数多く起こるため,プログラムの動作が遅くなる(今回のレポート問題).
字句解析 プログラムのソースコードを「単語(word)」に分解して,それがキーワードであるか, 数値である か,識別子であるか,演算子であるかなどを調べる.
構文解析 上の単語の並びから,実際にコンピュータでしなければならない動作を確定させる.
例えば, Cを例にとると,「数から始まる文字列」があれば,それは数値に変換されますし,アルファベットか ら始まる文字列なら,それは,キーワードか識別子のどちらかをチェックします(字句解析). また,(x+y)*zの 様な式があれば,x+yを計算してその結果に zを掛けるという動作をさせるように機械語を生成します(構 文解析).
このような動作ができるようにプログラミング言語の文法が決まっているわけですが, それを記述するのに よく用いられるのが, 拡張バッカスナウア記法(Extended Backus–Naur form, EBNF)です. EBNFで記述 されたプログラム言語の処理系を作成しようとすると,次のような複数の関数にまたがる再帰処理を書くのが 最も自然です(書く方も書きやすいし,読む方も読みやすい).
func1() {
...
func2();
}
func2() {
...
func3();
}
...
funcN() {
...
func1();
}
レポート問題
締切: 6月13日(月) 10:00(JST)
a0=a1= 1,an+1=an+an−1, (n≥1) で定義されるFibonacci(フィボナッチ)の数列について, 次の2 つのプログラムを書き,そのプログラムを提出するとともに, 3番目の結果をレポートせよ. ただし,どちらの 関数も,unsigned long long型(符号無し64bit整数)の変数を利用して,a50の正しい値が表示できるよう にすること. printfでのunsigned long longの出力の指定方法は,%llu. (man 3 printf を参照).
1. 繰り返し (for でも while でも良い) を用いて, 自然数 nの入力に対して, an を出力する関数 fibonacci(int n)を書き,main()では,a50を出力するプログラム.
件名: gengo2022 report 8-1.
2. 再帰を利用して, 自然数nの入力に対して,anを出力する関数fibonacci(int n)を書き,main()で は,a50を出力するプログラム.
件名: gengo2022 report 8-2
3. 上の2のプログラムの実行は終了するか? 2のプログラムが終了するなら,上の1, 2のプログラムにつ いてtimeコマンドでレポートされる内容を提出せよ.
件名: gengo2022 report 8-3.
timeコマンドは,time ./a.outで,a.outの実行に対して要したCPUの使用時間をレポートします.