プログラミング言語 2 第 07 回 (2007 年 06 月 25 日 ) 1 今日の配布物 片面の用紙 1 枚 今日の課題が書かれています 本日の出欠を兼ねています 2/27 1
今日やること http://www.tnlab.ice.uec.ac.jp/~s-okubo/class/language/ にアクセスすると 教材があります 2007 年 06 月 25 日分と書いてある部分が 本日の教材です 本日の内容 先週の課題の解答例 構造体 ( 前編 ) Lagrange の補間公式 3/27 第 07 回の課題の簡単な解説 4/27 2
第 07 回の課題 課題 1: 次の仕様を満たす関数 sample03 を作成しなさい sample03 は 引数として 2 つの整数 x,y を貰う x y + f, y + 2, x, x > 10 戻り値として 整数型の値 f ( x, y) = 2 を返す x 10 sample03 は f(x,y) を計算する際に 再帰を行なう 関数 sample03 の中からは 大域変数を参照しない 課題のポイント : 問題中のどこを再帰処理で行えばよいか 再帰の停止条件は きちんとできているか 問題に書き忘れていたこと : 今回 x は正の整数が入力されると仮定して良い 5/27 回答例 その1/1: ここでは 関数 sample03 のみ示す int sample03(int x, x, int y){ if(x<=10){ return x; x; else{ return y+sample03(x/2,y+2); 6/27 3
回答例 その1/1: int sample03(int x, x, int y){ if(x<=10){ return x; x; else{ return y+sample03(x/2,y+2); 停止条件 x 10 なら 再帰を行わず 値を返す さもなければ 再帰を行う 7/27 回答例 その1/1: int sample03(int x, x, int y){ if(x<=10){ return x; x; else{ return y+sample03(x/2 x/2,y+2); x なのに 2 x/2としか書いてない 整数型 / 整数型 = 整数型なので 小数点以下は 勝手に切り捨てられる 8/27 4
第 07 回の課題 課題 2:sample03 を使って f(63,5) を計算したときに どのように計算が行なわれていくか 説明しなさい 9/27 再帰の様子 sample03(63,5) の実行 01:int sample03(int x, int y){ 02: if(x<=10){ 03: return x; 04: else{ 05: return y+sample03(x/2,y+2); 06: 07: 02 :i > 10 なので else 文以下を実行 05 行 :5+sample03( 63/2,5+2) の計算のため sample03(2) を実行 sample03(31,7) の実行 02 :i > 10 なので else 文以下を実行 05 行 : 7+sample03( 31/2,7+2) の計算のため sample03(1) を実行 sample03(15,9) の実行 02 :i > 10 なので if 文以下を実行 04 行 : 9+sample03( 15/2,9+2) の計算のため sample03(7,11) を実行 sample03(7,11) の実行 02 行 :i 1 なので else 文以下を実行 04 行 : 戻り値として 7 を返す sample03(7,11)=7なので 16 を戻り値として返す sample03(15,9)=16なので 23 を戻り値として返す sample03(15,9)=23なので 28 を戻り値として返す 10/27 5
再帰の様子 式で再帰の様子を書くと... 01:int sample03(int x, int y){ 02: if(x<=10){ 03: return x; 04: else{ 05: return y+sample03(x/2,y+2); 06: 07: f ( 63,5) = 5 + f ( 63/ 2,5 + 2) = 5 + ( 7 + f ( 31/ 2,7 + 2) ) = 5 + ( 7 + ( 9 + f ( 15 / 2,9 + 2) )) = 5 + ( 7 + ( 9 + 7) ) = 5 + ( 7 + 16) = 5 + ( 23) = 28 11/27 再帰の様子 式で再帰の様子を書くと... 01:int sample03(int x, int y){ 02: if(x<=10){ 03: return x; 04: else{ 05: return y+sample03(x/2,y+2); 06: 07: f ( 63,5) = 5 + f ( 63/ 2,5 + 2) = 5 + ( 7 + f ( 31/ 2,7 + 2) ) = 5 + ( 7 + ( 9 + f ( 15 / 2,9 + 2) )) = 5 + ( 7 + ( 9 + 7) ) = 5 + ( 7 + 16) 戻り値を返す = 5 + ( 23) = 28 再帰呼び出し 戻り値を返す 戻り値を返す 再帰呼び出し 再帰呼び出し 戻り値を返す 停止条件を満たした 12/27 6
構造体 ( 前編 ) 13/27 構造体とは 構造体は 幾つかのデータをひとまとめにした型 たとえば 構造体 sample_kouzou 整数型のデータ 文字型のデータ 整数型のデータという 複数のデータを保存できる 文字型のデータ 構造体中の個々のデータを メンバと言う 次の場合に便利 関係している複数のデータを まとめて管理したいとき 関数に 沢山の値を引き渡したいとき 14/27 7
構造体を使うには 構造体を使うときは 次の手順を踏む必要がある 1. 構造体を定義する 2. 構造体の型をもつ 変数を宣言する 3. 変数にアクセスする 構造体は型なので その型をもつ変数を宣言して使います 15/27 構造体の定義 1. 構造体を定義定義するする 2. 構造体の型をもつ 変数を宣言する 3. 変数にアクセスする 構造体が どのようなメンバからなっているかを定義 書式は 次の通り struct 構造体の名前 {{ メンバーの宣言 たとえば 複素数を扱う構造体 complex を定義 struct complex {{ double real; double imaginary; ; ; 実数部保存用 虚数部保存用 2 つのメンバを持つ構造体 16/27 8
変数の宣言 1. 構造体を定義する 2. 構造体の型をもつをもつ 変数を宣言宣言するする 3. 変数にアクセスする 構造体は型なので その型を持つ変数を宣言する 書式は 次の通り struct 構造体の名前変数名 ;; たとえば 構造体 complex の型をとる変数 com01 と com02 と com03 を宣言するなら... struct complex com01, com02, com03; 17/27 変数の宣言 1. 構造体を定義する 2. 構造体の型をもつ 変数を宣言する 3. 変数にアクセスアクセスするする 構造体の それぞれのメンバにアクセスするには 変数名. メンバ名. のように 変数名とメンバ名を. でつなげて書く 変数 comp01 のメンバ real の内容にアクセスしたいなら... com01.real 18/27 9
変数の宣言 1. 構造体を定義する 2. 構造体の型をもつ 変数を宣言する 3. 変数にアクセスアクセスするする 例では com01 と com02 と com03 を宣言しているので 利用できるのは... com01.real com01.imaginary com02.real com02.imaginary com03.real com03.imaginary 普通の変数と同様に利用することができる com03.real = com01.real + com02.real; com03.imaginary = com01.imaginary + com02.imaginary; 19/27 サンプルプログラム 2 つの複素数 com01 と com02 の内容を足して com03 に代入し さらに com03 の内容を出力する その 1/2: #include<stdio.h> struct complex {{ double real; double imaginary; ; ; 2 つのメンバを持つ構造体 complex を定義 実数部保存用 虚数部保存用 20/27 10
サンプルプログラム main(){ struct complex com01, com02, com03; その 2/2: com01.real=2; com01.imaginary=3; com02.real=4; com02.imaginary=8; 値を代入 普通に計算 com03.real = com01.real + com02.real; com03.imaginary = com01.imaginary + com02.imaginary; printf("com03 is is %f %f + i i %f n",com03.real,com03.imaginary); 21/27 グラフのプロット ( 復習 ) 22/27 11
グラフのプロット 次の手順でグラフを書くことを考える 1. C で書いたプログラムで xgraph で読み込むデータを作る 2. xgraph で読み込んで グラフを書く xgraph で読み込むデータの形式 複数行からなっている 1つの行に2つの値が書かれている 2つの値は スペースで区切られている 23/27 #include<stdio.h> main(){ double x; x; xgraph で読み込むデータの作成 例として 4x 2 8x + 10 をプロットする 今回は 0 x 4 の間をプロットすることに for(x=0;x<=4;x=x+0.2){ printf("%f %f n",x,4*x*x-8*x+10); 今回は 0.2 刻みでプロットすることに 1つの行に 2つの値をスペースで区切って書く xと 4x 2 8x + 10 24/27 12
xgraph で読み込むデータの作成 さきほどのプログラムは 標準出力 ( 今はコンソール ) に対して 結果を出力する リダイレクトを使って 結果をファイルに出力する./a.out > xgraph.dat できたデータを xgraph でグラフにする xgraph xgraph.dat & 25/27 Lagrange の補間公式 26/27 13
Lagrange の補間公式 f(x) が 2 次以下の関数であるとする また a,b,c は異なる実数であるとする このとき f(x) は一意に定まり ( ) ( ) ( x b )( x c ) ( ) ( x c )( x a f x = f a + f b ) ( a b)( a c) ( b c)( b a) となる + f ( ) ( x a )( x b c ) ( c a)( c b) 27/27 14