なんか数学的な問題はぶっ飛ばして,高階関数に入りました.関数型言語っぽくなってなんかちょっとうれしい感じ.学部でMLやって以来の,久しぶりのわくわく感です!
問題1.29
simpson法で定積分を行うプログラムをつくってみました.
(define (sum term a next b) (if (> a b) 0 (+ (term a) (sum term (next a) next b)))) (define (square x) (* x x)) (define (cube x) (* x x x)) (define (simpson f a b n) (define (calc-h a b n) (/ (- b a) n)) (define h (calc-h a b n)) (define (next val) (+ val (* 2 h))) (* (/ h 3) (+ (f a) (f (+ a (* n h))) (* 4 (sum f (+ a h) next (+ a (* (- n 1) h)))) (* 2 (sum f (+ a (* 2 h)) next (+ a (* (- n 2) h))))))) (print (simpson square 0 1 100)) (print (simpson cube 0 1 100))
積分区間を[0,1]として,x**2,x**3を計算してみましたが,なんか出力が1/3,1/4とかなっててびっくりしました.というのも,有理数が出力されたので.どうなってんだこれ.なんでなんで?
と思ったら,整数の割り算してた.2 -> 2.0とかそういうことをやらないといけないのね.最近ずっとperlだったから忘れてました.
問題1.30
問題1.29の問題ででてきてるsumが線形再帰で効率が悪いとかで,反復的に計算できるsumを作ります.
(define (sum term a next b) (define (iter a result) (if (> a b) result (iter (next a) (+ result (term a))))) (iter a 0)) (define (inc x) (+ x 1)) (define (self x) x) (print (sum self 0 inc 10))
1から10を足してみたら55になったので,たぶん合ってるんじゃないかと.ブロック構造を使うと,外側でbindされた文字が使えるってところを忘れてて,けっこう長い間はまったりしまいました.そこさえ思い出せればなんとかなったみたいです.しかし,関数型のキホンって,反復構造なんだろうか.線形再帰を反復に書き直せって問題が多い気がします.
問題1.30
sum (Σ)じゃなくてproduct(Π)を作るそうです.sumを2箇所だけ変えるとできる.
(define (product term a next b) (define (iter a result) (if (> a b) result (iter (next a) (* result (term a))))) (iter a 1))
で、このproductをつかうと,階乗はこう書ける.
(define (inc x) (+ x 1)) (define (self x) x) (define (factorial n) (product self 1 inc n))
ついでに,π/4をWallisの公式で計算するのはこう.
(define (square x) (* x x)) (define (plus-2 x) (+ x 2)) (define (right-angle max) (/ (* 2.0 (product square 4 plus-2 max)) (* (+ max 1) (product square 3.0 plus-2 (- max 1)))))
ただ,あんまり計算を多くすると#
だったので,π/4とかなり違う.wallisの公式の限界ってやつですか?もしかして間違えてる?