オンラインSICP読書女子会 #2(1.1.7~1.1.8) まとめ

  • 3
    いいね
  • 1
    コメント
この記事は最終更新日から1年以上が経過しています。

#ladiescpp の主催してる オンラインSICP読書女子会 2 - connpassのまとめです〜。
まちがっているところがあればどんどんコメントください(`・ω・´)ゞ

次回の参加は オンラインSICP読書女子会 #3 (1.2.1~1.2.2) - connpass から!

参加者のブログ
オンラインSICP読書女子会 #2 (1.1.7~1.1.8) — miumixu's tech blog

1.1.7

ニュートン法による平方根のお話。

sqrt.scm

(define (improve guess x) (average guess (/ x guess)))

(define (average x y)
  (/ (+ x y) 2))

(define (good-enough? guess x)
  (< (abs (- (square guess) x)) 0.001))

(define (sqrt-iter guess x) (if (good-enough? guess x)
                guess
                (sqrt-iter (improve guess x) x)))


(define (sqrt x) (sqrt-iter 1.0 x))

練習問題1.6

1-6.scm

(load "./sqrt.scm")

(print (sqrt 5)) ;; 元のsqrt

 (define (new-if predicate then-clause else-clause)
   (cond (predicate then-clause)
    (else else-clause)))

(print (new-if (= 2 3) 0 5)) ;;正しく動くことを確認
(print (new-if (= 1 1) 0 5))

(define (sqrt-iter guess x) (new-if (good-enough? guess x)
                    guess
                    (sqrt-iter (improve guess x) x)))

(print (sqrt 5)) ;; new-ifをつかったsqrt. 無限ループに陥る

(if ⟨predicate⟩ ⟨consequent⟩ ⟨alternative⟩)
if 式を評価するにあたって、インタプリタは最初に式の ⟨predicate⟩ の部分
を評価します。もし ⟨predicate⟩ の評価結果が真である場合、インタプリタは
⟨consequent⟩ を評価し、その値を返します。そうでなければ ⟨alternative⟩ を評
価し、その値を返します。
(19P参照)

condについて試してみる。

(define (p) (p))

(cond (#t 0)
      (else (p)))

これは∞ループしない => elseは評価されていない。

if 同様 condも条件を頭から評価していく特殊形式

しかし、定義されたnew-ifは特殊形式ではない。
特殊形式でない式は引数が先にすべて評価してから、式を評価する。
そのため無限ループに陥った。

@hio さん

; new-if は特殊形式ではないので, 関数適用の実行前に全ての部分組み合わせの評価が
; 行われ, 結果 new-if の呼び出しの前に ``(good-enough? guess x)`` のみだけではなく
; ``guess`` そして ``(sqrt-iter (improve guess x) x)`` の評価も行われることになり
; sqrt-iter は無限の自己呼び出しに陥り, 制御を返さなくなってしまう.

@cocodrips

new-ifはただの関数みたいなものなので

new-if(foo(), bar())
は、foo() と bar()を評価してから new-if を評価するよね

練習問題1.7

まだ

小さい値
しきい値0.001の場合0.001より小さい値の予測値は、0.001より大きな誤差となってしまう。

(print (sqrt 0.01)) 
;; 0.1が正しい。
;;だいたい近づく 0.10032578510960605


(print (sqrt 0.0001)) 
;; 0.01のはすだが
;;0.03230844833048122

のようになる。

まだ検証不足。数学的にちゃんと示そう(今後の課題)

大きい値
(みんなで検証中)

練習問題1.8


@hioさん

(define (square x) (* x x))
(define (cube x) (* x x x))
(define (cbrt-iter guess x)
    (if (good-enough? guess x)
        guess
        (cbrt-iter (improve guess x) x)))
(define (improve guess x)
    (/ (+ (/ x (square guess)) (* 2 guess)) 3))
(define (good-enough? guess x)
    (< (abs (- (cube guess) x)) 0.001))
(define (cbrt x)
    (cbrt-iter 1.0 x))

; gosh> (cbrt 1)
; 1.0
; gosh> (cbrt 8)
; 2.000004911675504
; gosh> (cbrt 27)
; 3.0000005410641766
; gosh> (cbrt 64)
; 4.000017449510739
; gosh> (cbrt 42)
; 3.476026657071078
; gosh> (* 3.476026657071078 3.476026657071078 3.476026657071078)
; 42.000000441671865
; gosh> (cbrt 57)
; 3.8485043229942804
; gosh> (cube (cbrt 57))
; 57.00014181732636

===

@miumixuさん

(define (improve guess x)
  (/ (+ (/ x (square guess))
        (* 2 guess))
     3))

(define (good-enough? guess x)
  (< (abs (- guess (improve guess x))) 0.001))

(define (cbrt-iter guess x)
  (if (good-enough? guess x)
      guess
      (cbrt-iter (improve guess x) x)))

(define (cbrt x)
  (cbrt-iter 1.0 x))

1.1.8ブラックボックス抽象化としての手続き

モジュールとして使えるようにプログラムを分解しよう〜ってお話でした。