計算機プログラムの構造と解釈(SICP) 勉強メモ6
今日は気分があまり乗らないので、ここでSICPはSTOPして違うことしようかな。
問題1.7から1.1.8まで。
;問題1.7 ;小さい数は ;(sqrt 0) => 0.03125 ;0の平方根は0だが、ここでは0.03125が返ってくる。 ; ;大きい数は ;(sqrt 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999) ;ここまでは平気だが ;(sqrt 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999) ;までいくと ;(sqrt-iter 1.0e45 9999999999999999999999999999 ... ;sqrt-iterのguessが常に同じ値となり、無限ループに陥る。 ; (define (good-enough? guess x) (if (and (> (/ (improve guess x) guess) 0.999) (< (/ (improve guess x) guess) 1.001)) #t (< (abs (- (square guess) x)) 0.001))) ;大きな値では次のguessと現在のguessが殆ど同じ(0.999~1.001)場合に#tを返して処理を止める。 ;しかし、小さな値(例えば0)では比が常に0.5になるのでこの方法では小さい値は上手く働かない。 ;問題1.8 (define (curt-iter guess x) (if (curt-good-enough? guess x) guess (curt-iter (curt-improve guess x) x))) (define (curt-improve guess x) (/ (+ (/ x (square guess)) (* 2 guess)) 3)) (define (curt-good-enough? guess x) (if (and (> (/ (curt-improve guess x) guess) 0.999) (< (/ (curt-improve guess x) guess) 1.001)) #t (< (abs (- (square guess) x)) 0.001))) (define (curt x) (curt-iter 1.0 x)) ;;1.1.8 ブラックボックス抽象としての手続き ; sqrtは相互に定義する手続きの組として定義したプロセスの最初の例である。 ;sqrt-=iterの定義は再帰的(recursive)であることに注意して欲しい。 ;つまり、手続きはそれ自身を使って定義してある。 ; ; 分割戦略は単にプログラムを部分に分けることより重要である。 ;大きなプログラムを最初の10行、次の10行のように分けるのではなく、 ;各手続きは他の手続きを定義するとき、その部品として使え、まとまった仕事が出来ることが重要だ。 ;例えばsquareを使ってgood-enogh?手続きを定義する時、われわれはsquare手続きを「ブラックボックス」と見ることが出来る。 ; ; 手続きのパラメタ名は手続き本体に対して、局所的でなければならない。 ;手続きの仮パラメタには、手続き定義の中で、仮パラメタがどんな名前を持っていても構わない。 ;そういう名前を束縛変数(bound variable)といい、手続き定義は仮パラメタを束縛する(bind)という。 ;変数が束縛されていなければ、自由である(free)という。 ;名前が束縛されている式の範囲を有効範囲(scope)という。 ;good-enough?の定義では、guessとxは束縛変数だが、<,-,abs,squareは自由である。