プログラミング論I 工学部2015年度 – プログラミング論I – 2015年 度前期 (廣川) 工学部大講義室(月曜1,2限目) プログラミング論I • • • • 2年生前期:毎週月曜日1,2限目 目標:プログラムの基本設計法を習得 使用プログラミング言語:Scheme (後述) 単位取得:講義時の平常点+試験 – 出席点:10点,演習課題:20点,試験:70点 なぜプログラミングを学習するか 右下図:http://www.kkr.mlit.go.jp/river/keyword/images/03_01.jpgより • 今やコンピュータは社会基盤の一部 – コンピュータソフトウェアに関する素養は必須 • コンピュータはデータを形式的(機械的)に処理 – 特定の言語によらず、データおよびその処理手順(プログラム)を論 理的に記述する(というプログラミング)能力は重要 その際には • テクニックよりまず基本的な考え方を重視 – 問題分析、問題解決の技術 プログラミングは,この訓練になる プログラム設計法(レシピ) プログラム設計レシピ:問題解決過程のガイド 1. 2. 3. 4. 5. 6. 問題の解析とデータの定義 規約、目的、結果の記述とヘッダ作成 例題を用いたプログラムの振舞の例示 プログラムテンプレート、レイアウトの作成 テンプレートを完全な定義に変換 テストを通してエラーの発見 各ステップで中間生成物をチェック (具体的な適用法や設計ごとのバリエーションは後述) ソフトウェア開発と言語 • ソフトウェア開発(抽象レベルでは言語非依存): – 物理システムの開発と同様きちんとした抽象化、設計法 – 物理法則のような制約がない→論理的正しさが特に重要 • 具体的実現:目的に適した言語(モデル)を選択 – モデル: 式、関数 / 手続き、副作用 / オブジェクト指向 等 – 目的:科学技術計算、事務処理、システムソフト、DBなど • 本講義:基本的 「式、関数」 をベースとした言語 – Scheme という言語を使う Scheme の特徴 • 関数型: 数学体系λ計算が基礎 – 式(関数)でプログラムを構成、式の簡約で計算が進む • 紙と鉛筆(頭の中)でもプログラム実行過程が追える • インタプリタ型処理系 – 初学者にも優しい(本質が埋もれがちな作業が少ない) • 見た目としては演算子が前置記法で括弧が多い – プログラムの基本単位である式を括弧で囲む – 式の構成要素にまた式を持ち得る(括弧の入れ子) 例 4×2 + 4÷2 の表記とその計算過程: (+ (* 4 2 ) (/ 4 2)) → (+ 8 (/ 4 2)) → (+ 8 2) → 10 Scheme についての参考資料 • 参考書 – [この講義] M. Felleisen et al., "How to Design Programs", MIT Press (Web版 http://www.htdp.org/) – [Scheme言語仕様] ケント ディヴィグ (村上雅章 訳), "プログ ラミング言語SCHEME", ピアソン・エデュケーション – [言語として Scheme を用いる他の著名な講義用テキスト] サスマン他 (和田英一訳), "計算機プログラムの構造と解 釈", ピアソン・エデュケーション プログラミング論Iの予定 • 前半:データに着目したプログラム開発の基本 • • • • 数と数式、プログラムと実行過程、エラー 変数と関数、条件、プログラム設計法によるプログラム作成 様々なデータ(atomic/複合データ)およびその処理 任意長データと処理(リストと再帰処理プログラム) • 後半:プログラミングに関するより高度な話題 • • • • • 設計の抽象化 値としての関数を使った抽象化 (高階関数) 再帰のバリエーション 知識の蓄積(アキュムレータ) 学習成果を使った様々な例題 • 非関数的なプログラミング • 副作用(代入)、状態更新、外界との入出力 プログラミング論Iの進め方 • 「情報処理演習II」とゆるやかに連動 – プログラミング論I → 講義(例題を交えた説明) • レシピ(設計のガイド)や例(理解の促進)を重視 • 講義資料などはすべて WWW で公開 http://matu.cc.kyushu-.ac.jp/~hirokawa/Programming/ Racket (Scheme処理系) • http://download.racket-lang.org/ 自分のPCに合う物を 選択してください DrRacketの起動画面 Language Choose Language プログラムの記述(1/2) (+ 1 2) (* 3 4) (/ 5 6) (- 7 8) 3 12 0.83 -1 この画面にプログラムを 書いて,RUNを押す 式の値が, 下の画面に現れる プログラムの記述(2/2) ;; 1 dollar is 121.77 yen ;; d dollars is 121.77*d yen ;; d2y: number -> number ;; (d2y 3) should return 121.77*3=365.31 (define (d2y d) 関数定義の例 (* 121.77 d)) (d2y 3) 365.31 この画面にプログ ラムを書いたら, Enterを押す この画面にプログラムを 書いたら,RUNを押す C言語での定義 の例 #include <stdio.h> double d2y(double d){ return (121.77*d); } int main(){ double d; Visual Studio printf(“d=“); の場合 scanf_s("%lf", &d); printf("%f\n", d2y(d)); return (0); } 1. Scheme の式とプログラム 数、式、プログラムと実行過程、エラー 本日の内容 • Scheme プログラムとその処理系の概要 • Scheme の簡単な式 • Scheme の簡単な関数 • プログラムの実行過程 • エラー Scheme プログラム データを処理(および入/出力)する手順の記述 • データ: – 単体(atomic)データ – 複合(compound)データ 複数のデータで構成 (固定サイズ、任意サイズ) • 処理: – 基本(primitive)演算・関数 – 既存の関数を部品として使う関数 対象問題を解くため, これらを使った解決 手順を書く: → プログラミング (本講義は基礎) Scheme の実行イメージ 計算手順をSchemeで記述 作成・保存済の Scheme プログラムの呼出も可能 コンピュータ上のインタプリタ (解釈・実行ソフト) 計算が行われ,結果の表示 実行結果 参考:コンパイラ型のC言語 手順をC言語で記述 コンピュータ上の コンパイラ (翻訳ソフト) 実行可能形式に変換 コンピュータ上で実行 実行結果 Scheme の文法(基本レベル) プログラミング言語も言語:語彙を文法に従って書き並べる 語彙 • 変数 • 定数:数、記号、真偽値 5 -5 0.5 'a true など • primitive演算子 + - * / remainder quotient max min abs sqrt expt log sin cos tan など 文法 • 式 – 定数、変数、 式、(演算子 式…) 基本的に前置記法 • 定義 – (define (変数…) 式) これ以外にもあるが,適宜授業で説明 Scheme の式の例 - 四則演算 • (+ 5 5) • (+ -5 5) 負の数も扱える • (+ 0.5 0.5) 実数も扱える • (- 5 5) • (* 3 4) • (/ 8 12) + - * / などが使える * は掛算、 / は割算 処理系(DrRacket)での実行結果の例 入力を促す「プロンプト」 計算したい式 計算結果 式を入力すると,計算が行われ、 結果が表示される。 (処理系の DrRacketの詳細は基礎演習で) Scheme の式の例 - 各種の演算 • (remainder 100 15) ;; 100 を 15 で割った剰余(=10) • (quotient 100 15) ;; 100 を 15 で割った商(=6) • (max 3 5) ;; 3, 5 の大きい方 (=5) • (min 3 5) ;; 3, 5 の小さい方 (=3) • (abs -10) ;; -10 の絶対値 (=10) 実行結果の例 処理系では式を入力すると, 計算が行われて表示される Scheme の式の例 -入れ子の式と括弧 (3 5) * (30 / 10) ( 2 2) * 2 • Scheme 言語で書くと: (* (+ 2 2) (/ (* (+ 3 5) (/ 30 10)) 2)) Scheme の式 括弧の意味 (3 5) * (30 / 10) ( 2 2) * 2 (* (+ 2 2) (/ (* (+ 3 5) (/ 30 10)) 2)) 括弧が,計算の「単位」を表現している。 優先順位が高い単位から先に括弧で括る。 計算過程 最初に最内のカッコで括られた式を数に簡約、 引き続き次の入れ子の層の計算を続ける (* (+ = (* 4 = (* 4 = (* 4 = 48 2 2) (/ (* (+ 3 5) (/ 30 10)) 2)) (/ (* 8 3) 2)) (/ 24 2) ) 12) 左から右に,簡約が進む Scheme式の形式: (operation A ... B) 計算規則:A...B が全て値ならoperationは計算可能。 そうでなければA...Bのうち値でないものをまず値に 練習1:Scheme 式 次の計算を行う Scheme の式を書き、結果も示せ 5+5 -5 + 5 3*4 8 / 12 3 + 4.5 (2 + 2) * (((3 + 5) * (30 / 10)) / 2) >(+ 5 5) 10 >(+ -5 5) 0 >(* 3 4) 12 >(/ 8 12) 2/3 >(+ 3 4.5) 7.5 >(* (+ 2 2) (/ (* (+ 3 5) (/ 30 10)) 2)) >(* 4 (/ (* (+ 3 5) (/ 30 10)) 2)) >(* 4 (/ (* 8 (/ 30 10)) 2)) >(* 4 (/ (* 8 3) 2)) >(* 4 (/ 24 2)) >(* 4 12) 48 プログラムの構成要素:変数定義 ものには名前をつけることができる(定義) 通常、プログラムは数多くの定義からなる • 関数定義:主関数、補助関数(後述) • 変数定義(Variable Definition) 値に名前を与える。ある値が何度も出現するときなどに有用 一般形: (define 変数名 値) 例:円周率 π を3.14とする (define PI 3.14) PIの参照を3.14 で置き換える: DrRacket の実行例 > (define PI 3.14) > PI 3.14 プログラムとその構成要素:関数定義 計算等の実行手順 (前述のような式や定義から 構成)にも名前をつけることができる:関数定義 Scheme の関数定義の例 半径rの円の面積を求める 関数area-of-diskを定義 (define (area-of-disk r) (* PI (* r r))) area-of-disk (r) = PI * r 2 円の面積を求める関数の定義例: • 半径 r の値から円の面積 (* PI (* r r)) を計算 する手順に area-of-disk という名前をつけている 円の面積 r (円の面積) 半径 r の円の面積は π r2 円の面積を求める関数の定義 (define (area-of-disk r) (* PI (* r r))) この部分は Scheme の式 (実行時に指定される半径は 変数 r として表現) 円の面積を求める関数の定義 (define (area-of-disk r) (* PI (* r r))) 実行時に値を1つ(名前はr)受取る 関数の引数(パラメータ)という 内部の式ではrの値から(* PI (* r r))を計算 関数を使ったプログラム • プログラム中における関数の実行(関数適用) – 入力(与えるデータ)と出力(受け取る結果)がある – 定義名(手順に付けられた名前)と必要な入力デー タを与えて計算を呼び出す。 area-of-disk (r) = PI * r 2 入力 r の値: 5 (area-of-disk 5) area-of-disk の定 義本体部分を呼び出す (このとき r は5で置換) (* PI (* 5 5)) = (* 3.14 25) = 78.5 出力 78.5 まとめ • 関数 = プログラムの構成単位 「関数定義である」ことを 示すキーワード 関数の名前 (define (area-of-disk r) (* PI (* r r))) r の値から(* PI (* r r)) を計算(出力) 関数 定義 引数として値を1つ 受け取る(入力) C言語での例 //(define PI 3.14) //(define (area-of-disk r) (* PI (* r r))) #include <stdio.h> #include <math.h> double area_of_disk(double r){ return (M_PI * r * r); // M_PIはmath.hの中で定義 } int main(){ double r=5.0; printf(“%f”,area_of_disk(r) ); return(0); } 練習2. 以下で、計算の精度を上げるためにPIの 小数点以下を一桁増やすにはどうしたらよ いか。また r が5の時の結果はどうなるか。 (define PI 3.14) (define (area-of-disk r) (* PI (* r r))) 練習2. 解答 以下で、計算の精度を上げるためにPIの 小数点以下を一桁増やすにはどうしたらよ いか。 (define PI 3.141) (define (area-of-disk r) (* PI (* r r))) また r が5の時の結果はどうなるか。 >(area-of-disk 5) (* PI (* 5 5)) (* 3.141 25) 78.525 練習3:関数定義 二数の和を求める関数 wa と積を求める 関数 seki を作成し,実行例を示せ 解答例: (define (wa x y) (+ x y)) 実行例: > (wa 10 20) 30 練習3:関数定義(解答) 二数の和を求める関数 wa と積を求める 関数 seki を作成し,実行例を示せ 解答例: (define (wa x y) (+ x y)) (define (seki x y) (* x y)) 実行例: > (wa 10 20) 30 > (seki 10 20) 200 間違いの例:構文エラー • 「スペース(空白文字)」に意味がある • 括弧に注意 間違いの例 1 間違いの例 2 (* (+2 2) (* (+ 2 2) (/ (* (+ 3 5) (/ (* (+ 3 5) (/ 30 10)) (/ 30 10)) 2)) 2) ) +の後にスペースが無い 括弧の不足 種々のエラー • 構文エラー(Syntax Errors) 処理系が見つける (DrRacket) • 言語Schemeの文法に合っていない場合 e.g. (10) (10 + 20) • 実行時エラー(Run-time Errors) • Schemeの文法に合っているが,結果を返さな い場合. e.g. (/ 1 0) (define (f n) (+ (/ n 3) 2)) に対する (f 5 8) • 論理的エラー(Logical Errors) • Schemeの文法に合っていて,結果も返すが,その結果が 間違っている場合(多くの場合は原因の特定が困難) e.g. (define (area-of-triangle b h) (+ b h)) 注意深く論理的に正しく プログラムを設計するこ とで回避 → 設計レシピ (define (wage h) (+ 12 h)) 問題 • 次は、何エラーというか? • (10 + 20) • (define (P x) (+ (x) 10)) に対する(P 5) • (define (f n) (+ (/ n 3) 2)) に対する(f 10 20) ;; area-of-ring:半径rの円の面積を求める • (define (area-of-ring r) (* 2 PI r)) 今日の練習問題 課題1. ドルから円への変換 • ドル d から円を求める関数 d2y を作成 し,実行例を示すこと – 関数の定義には define を使う – 1ドルは,120.70円とする (2014/12/09 現在) (define Yen/Dollar 120.70) ;;d2y: number -> number ;;(d2y 1) should return 120.70 (define (d2y dollar) (* dollar Yen/Dollar)) (d2y 1) #include <stdio.h> double YenDollar=120.70; double d2y(double d){ return (d * YenDollar); } int main(){ double d=1.0; printf(“%f”,d2y(d)); return (0); } 課題のヒント(解答例) • x から「10 × x + 30」 を求める関数 foo を作成し,実行結果を報告しなさい 解答の例: (define (foo x) (+ (* 10 x) 30)) 実行結果は次の通りと期待される (foo 10) は 130 (foo 20) は 230 (あくまでも例です.各自、工夫を試みてください. 独自の工夫を高く評価します) 課題のヒント • ここにあるのは「間違い」の例です.同じ間違い をしないこと 1. 「かっこ」の間違い define (d2y d) (* 120.53 d) ⇒ 全体をかっこで囲むこと 2. 変数名の対応の間違い (define (d2y dollar) (* 120.53 d)) ⇒ 変数名dとdollarはどちら かに統一すること(どちらでも可) 3. 関数の書き方の間違い (define (d2y) (* 120.53 d)) ⇒ d2y の後に d が必要 4. 関数名の付け方の間違い (define (d 2 y d) (* 120.53 d)) ⇒ 「d 2 y」でなく 「d2y」 と書くこと 課題2. 摂氏から華氏への変換 • 摂氏(Celsius)表現の温度 c から華氏 (Fahrenheit)表現の温度 f を求める関 数 c2f を作成し,実行例を示しなさい – 関数定義には define を使う – 摂氏と華氏の変換式: c=5 ×(f - 32) / 9 ;;c2f : number -> number ;; f = 9/5 * c + 32 ;;(c2f 5) should return 41 (define (c2f c) (+ (* (/ 9 5) c) 32)) 課題3. 元利の計算 (define (interest base rate year) • (* base (expt (+ 1 rate) year))) 元金と年利と年数を受け取り、元利を求める 関数 interest を作成し,実行例を示せ – 関数定義には define を使う – 元利の計算式: 「元利 = 元金 × (1+年利)年数」 – 作成した関数を実行し,元金1000円,年利2%で の,50年後の元利を報告しなさい – x の y 乗の計算には exptを使う:(expt x y) 2691.5880290736053938940873551... の値が返る
© Copyright 2024 ExpyDoc