放射状

勉強のメモ。

SICP五日目~ 問題 1.8

schemeとF#を平行にやっているとじんわりと胸に広がる、「やっぱり副作用がないHaskellやっとかないとだめなんじゃ…」疑惑。でも「そんなに言語ばっかりやってどうすんの」疑惑もあり。もっと勉強するべきことがあるのでは(Hadoopとか)(もっと基本的な数学とか)疑惑もあり。
迷ってばかりですが、とりあえず手を動かします。

問題1.8

問題はここから平方根の章もようやく最後です。今回は簡単でした。
問題1.7で改善したプログラムの、average関数を立方根の近似値を求めるapproximate関数に置き換えるなどしました。

(use slib)
(require 'trace)

(define (cube x) (* x (square x)))

(define (cubeRootRec guess x)
  (if (good-enough? guess x)
      guess
      (cubeRootRec (improve guess x) x)
  ))

(define (good-enough? guess x)
  (if (< (abs (- (improve guess x) guess)) 0.0001)
     #t
    (< (abs (- (cube guess) x)) 0.001)
    )      
  )

(define (improve guess x)
  (approximate x guess)
  )

;近似値を求める計算
(define (approximate x y) 
  (/ (+ (/ x (square y)) (* 2 y)) 3) 
)

(define (cubeRoot x)
  (cubeRootRec 1.0 x)
  )

;トレース指定
(trace cubeRootRec)
;実行
(cubeRoot 3.0)

これを実行すると、

gosh> CALL cubeRootRec 1.0 3.0
  CALL cubeRootRec 1.6666666666666667 3.0
    CALL cubeRootRec 1.471111111111111 3.0
      CALL cubeRootRec 1.442812098249343 3.0
        CALL cubeRootRec 1.4422497895989996 3.0
        RETN cubeRootRec 1.4422497895989996
      RETN cubeRootRec 1.4422497895989996
    RETN cubeRootRec 1.4422497895989996
  RETN cubeRootRec 1.4422497895989996
RETN cubeRootRec 1.4422497895989996
1.4422497895989996

良い感じに動いているようですね!

ここまでやってみて

lispはシンプルできれいで強力で触っていて非常に楽しいのですが、括弧の数をとにかく間違えます。驚くほど間違えます。そしてGaucheに怒られます。
記載されているソースコードのインデントや改行のタイミングにも注意してSICPを読み込まないとだめですね。