1 / 111

8. 高階関数を用いた抽象化

8. 高階関数を用いた抽象化. 例題. 例題1.接線の傾き. 接線の傾きを求める関数 d/dx を定義し,実行する 数値 x , h と関数 f から, x における f の傾き ( つまり f '(x) ) の近似値を求める. 傾きは. f(x). 接線. x. 0. 入力と出力. f2 3 0.0001. f2'(3) の近似値. d/dx. 出力. 入力. 出力は数値. 入力は2つの数値と 関数. d/dx は,関数を入力とするような関数 (つまり高階関数). Contract ( 規約 ).

lewis
Download Presentation

8. 高階関数を用いた抽象化

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 8. 高階関数を用いた抽象化

  2. 例題

  3. 例題1.接線の傾き • 接線の傾きを求める関数 d/dxを定義し,実行する • 数値x, hと関数 fから,xにおける fの傾き (つまり f'(x) ) の近似値を求める 傾きは f(x) 接線 x 0

  4. 入力と出力 f2 3 0.0001 f2'(3) の近似値 d/dx 出力 入力 出力は数値 入力は2つの数値と 関数 d/dxは,関数を入力とするような関数 (つまり高階関数)

  5. Contract (規約) d/dx 関数の Contract(規約) d/dx: (number->number) number number -> number 関数 入力:数値 出力:数値 数値 数値 数値 出力 入力

  6. d/dx 関数 ;; d/dx: (number->number) number number -> number ;; inclination of the tangent ;; Example: (d/dx f 3 0.0001) ;; = ((- (f 3.0001) (f 2.9999)) 0.0002) (define (d/dxf x h) (/ (- (f (+ x h)) (f (- x h))) (* 2 h))) 関数が, 「d/dx」の入力になっている

  7. まず,関数d/dxを定義している

  8. 次に関数 f2を定義している (define (f2x) (- (* x x) 2))

  9. これは, (d/dxf2 3 0.0001) と書いて,xの値を 3 に, hの値を 0.0001 に, fを f2に設定して実行  実行結果である「6」が 表示される 

  10. (d/dx f2 3 0.0001) から 6 が得られる過程の概略 最初の式 (d/dx f2 3 0.0001) = (/ (- (f2 (+ 3 0.0001)) (f2 (- 3 0.0001))) (* 2 0.0001)) = ... = (/ (- (- (* 3.0001 3.0001) 2) (f2 (- 3 0.0001))) (* 2 0.0001)) = ... = 6 コンピュータ内部での計算 実行結果 但し,f2は (define (f2x) (- (* x x) 2))

  11. (d/dx f2 3 0.0001) から 6 が得られる過程の概略 (d/dx f2 3 0.0001) = (/ (- (f2 (+ 3 0.0001)) (f2 (- 3 0.0001))) (* 2 0.0001)) = ... = (/ (- (- (* 3.0001 3.0001) 2) (f2 (- 3 0.0001))) (* 2 0.0001)) = ... = 6 これは, (define (d/dxf x h) (/ (- (f (+ x h)) (f (- x h))) (* 2 h))) の xを 3 で,hを 0.0001 で, fを f2で置き換えたもの

  12. (d/dx f2 3 0.0001) から 6 が得られる過程の概略 (d/dx f2 3 0.0001) = (/ (- (f2 (+ 3 0.0001)) (f2 (- 3 0.0001))) (* 2 0.0001)) = ... = (/ (- (- (* 3.0001 3.0001) 2) (f2 (- 3 0.0001))) (* 2 0.0001)) = ... = 6 これは, (define (f2x) (- (* x x) 2)) の xを (+ 3 0.0001)=3.0001で置き換えたもの

  13. 例題2.べき級数 • べき級数を求める高階関数 power_seriesを定義する • 自然数 n,数x,関数 g から (* (g 0)(expt x 0)) + (* (g 1)(expt x 1)) + …+(* (g n)(expt x n))  を求める • n = 0 の時 • n > 0 の時

  14. 級数とべき級数 • 級数 (series関数で実現可) • べき級数 • べき級数の各項を f(k) と考えると級数と同じ手順で計算できることが分かる • この f(k) には,関数 g と値 x を与えないと計算できない

  15. Contract (規約) power_series 関数の Contract(規約) ;;power_series: number N (N->number) -> number 数値 自然数 関数 入力:自然数 出力:数値 数値 出力 入力

  16. 入力と出力 (g1 0), (* (g1 1) (expt 2 1)), (* (g1 2) (expt 2 2)), (* (g1 3) (expt 2 3)) の値の合計 2 3 g1 power_series 出力 入力 出力は数値 入力は2つの数値と 関数 power_seriesは,関数を入力とするような関数 = 高階関数

  17. べき級数 power_series 関数 ;; series: N (N -> number) -> number ;; sum up the first n numbers in the sequence f ;; (series 3 f2) = (+ (f2 3) (+ (f2 2) (f2 1))) (define (seriesn f) (cond [(= n 0) (f 0)] [else (+ (f n) (series (- n 1) f))])) ;; power_series: number N (N -> number) -> number (define (power_seriesx n g) (local ((define (power_termi) (* (gi) (expt x i)))) (seriesn power_term) ) )

  18. 定義の局所化 (local式) ;; series: N (N -> number) -> number ;; sum up the first n numbers in the sequence f ;; (series 3 f2) = (+ (f2 3) (+ (f2 2) (f2 1))) (define (seriesn f) (cond [(= n 0) (f 0)] [else (+ (f n) (series (- n 1) f))])) ;; power_series: number N (N -> number) -> number (define (power_seriesx n g) (local ((define (power_termi) (* (gi) (expt x i)))) (seriesn power_term) ) ) series関数:  級数 Σf(k) を求める 関数 power_termは,関数 power_series内の 局所(local)関数として定義されている

  19. べき級数 power_series 関数 ;; series: N (N -> number) -> number ;; sum up the first n numbers in the sequence f ;; (series 3 f2) = (+ (f2 3) (+ (f2 2) (f2 1))) (define (seriesn f) (cond [(= n 0) (f 0)] [else (+ (f n) (series (- n 1) f))])) ;; power_series: number N (N -> number) -> number (define (power_seriesx n g) (local ((define (power_termi) (* (gi) (expt x i)))) (seriesn power_term) ) )

  20. 関数 series,関数 power_series を定義している

  21. 関数 g1を定義している (define (g1n) n)

  22. これは, (power_series 2 3 g1) と書いて,xの値を 2に,nの値を 3に,gの値を g1に設定して実行  実行結果である「34」が 表示される 

  23. べき級数 power_series の計算例(概略) 最初の式 power_series を使い簡単なべき級数 x + 2x2 +…+ nxn を計算 但し x=2, (define (g1n)n) (power_series 2 3 g1) = (local ((define (power_term i) (* (g1 i) (expt 2i)))) (series 3 power_term)) = (local ((define (power_term i) (* (g1 i) (expt 2i)))) (+ (power_term 3) (series 2 power_term)))) = ... = (local ((define (power_term i) (* (g1 i) (expt 2i)))) (+ (power_term 3) (+ (power_term 2) (+ (power_term 1) (power_term 0))))) = ... = (+ (* (g1 3)(expt 2 3)) (+ (* (g1 2)(expt 2 2)) (+ (* (g1 1)(expt 2 1)) (* (g1 0)(expt 2 0))))) = ... = (+ 24 (+ 8 (+ 2 0))) = ... = 34 実行結果

  24. 「(power_series 2 3 g1)」 は 関数の中身で置き換わる

  25. 「power_term」は局所関数「power_term_0」で 置き換わる.(_0は局所関数を示す番号) 

  26. 「(series 3 power_term_0)」 は 関数の中身で置き換わる

  27. 「(= 3 0)」 は 「false」で置き換わる

  28. 「(false (power_term_0 0))」 は 消える

  29. 「(cond (else ...))」 は 「...」の部分で置き換わる

  30. 「(power_term_0 3)」 は 関数の中身で置き換わる

  31. 「(g1 3)」 は 「3」で置き換わる

  32. 「(expt 2 3)」 は 「8」で置き換わる

  33. 「(* 3 8)」 は 「24」で置き換わる

  34. 「(- 3 1)」 は 「2」で置き換わる

  35. 「(series 2 power_term_0)」 は 関数の中身で置き換わる

  36. 「(= 2 0)」 は 「false」で置き換わる

  37. 「(false (power_term_0 0))」 は 消える 以後省略

  38. 実習

  39. 実習の進め方 • 資料を見ながら,「実習」を行ってみる • その後,各自「課題」に挑戦する • 各自で自習 + 巡回指導 • 遠慮なく質問してください • 自分のペースで先に進んで構いません

  40. DrScheme の使用 • DrScheme の起動 プログラム → PLT Scheme → DrScheme • 今日の実習では「Intermediate Student」 に設定 Language → Choose Language → Intermediate Student → OK ボタン

  41. DrScheme の使用 / ステップ実行 • プログラム実行の振る舞いを観察するツール • 「定義用ウインドウ」のみを使用 (通常の実行と異なる) • 「Intermediate Student」に設定する必要あり Language → Choose Language → Intermediate Student → Run ボタン

  42. 実習1.階乗 • 階乗を計算する関数 !を定義し,実行する • 次の方針でプログラムを作成する n > 0 のとき,n! = n × (n - 1)! 例) 6! = 6×5!

  43. 階乗 • n = 0 のとき • n > 0 のとき

  44. 「実習1.階乗」の手順 • 次を「定義用ウインドウ」で,実行しなさい • 入力した後に,Run ボタンを押す ;;! : number -> number ;;to compute n*(n-1)*...*2*1 (define (!n) (cond [(= n 0) 1] [else (* n (! (- n 1)))])) • その後,次を「実行用ウインドウ」で実行しなさい (! 3) (! 4)

  45. 「実習1.階乗」の実行結果

  46. 入力と出力 24 4 ! 出力 入力 入力は数値 出力は数値

  47. ! 関数 ;; ! : number -> number ;; to compute n*(n-1)*...*2*1 ;; Example: (! 4) = 24 (define (!n) (cond [(= n 0) 1] [else (* n (! (- n 1)))])) 0! = 1 である n! は (n-1)! を計算して,n を掛ける

  48. 階乗 • n = 0 ならば:  → 終了条件 1 → 自明な解 • そうで無ければ:  • 「(n – 1) の階乗」に n をかける ⇒ 結局,1 から n までのかけ算を繰り返す

  49. 階乗 ;; ! : number -> number ;; to compute n*(n-1)*...*2*1 ;; Example: (! 4) = 24 (define (!n) (cond [(= n 0) 1] [else (* n (! (- n 1)))])) 自明な解 終了条件

  50. 終了条件 No (= n 0) Yes (* n (! (- n 1))) 1 が自明の解

More Related