SICP(1.1 プログラムの要素)の問題を解いてみた

計算機プログラムの構造と解釈SICP)の「1.1 プログラムの要素」を読んで、問題を一部解いてみました。
sicp/chapter_1 at master · matk2/sicp · GitHub

以下に、一部の回答について説明を行おうと思います。

問題1.3

三つの数を引数としてとり、大きい二つの数の二乗の和を返す手続きを定義せよ。

回答
(define (sum-of-square-with-large-num a b c)
  (define minimum
    (cond ((and (<= a b) (<= a c)) a)
          ((and (<= b a) (<= b c)) b)
          (else c)))

  (cond ((= minimum a) (sum-of-square b c))
        ((= minimum b) (sum-of-square a c))
        (else (sum-of-square a b))))

(define (sum-of-square x y) (+ (square x) (square y)))

手続き実行結果

(sum-of-square-with-large-num 1 3 2)
13

(sum-of-square-with-large-num 100 50 1)
12500
  • 三つの数を引数としてとり、大きい二つの数の二乗の和を返す手続きとして、sum-of-square-with-large-numを定義した
  • 二つの数の二乗の和を返す手続きとして、sum-of-squareを定義し、cond式内で繰り返し使用できるようにした
  • 三つの引数の内、最小値を特定する手続きとして、minimumsum-of-square-with-large-numの内部に定義し、sum-of-square-with-large-numが呼び出されたときの引数から値(a、b、c)をとるようにした

問題1.8

立方根をとるNewton法はyがxの立方根の近似値なら、よりよい近似値は
(x/y2 + 2y)/3
の値で与えられるという事実によっている。この式を使い立方根の手続きを実装せよ。

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

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

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

  (cbrt-iter 1.0))

実行結果

(cbrt 8)
2.000004911675504

(cbrt 125)
5.00003794283566
  • 立方根を求める手続きとして、cbrtを定義し、その内部に、cbrt-iter(近似値が十分に正確な値かどうかを検証し、不十分な場合はよりよい近似値を求める手続き)、good-enough?(近似値が十分に正確な値かどうかを検証する手続き)、improve(よりよい近似値を求める手続き)を定義した
  • 近似値が十分に正確だと判断する条件は、近似値の変化(割合)の差分の絶対値が0.001未満であることとした(ex. 現時点で求まっている近似値が1000だとした場合、次のよりよい近似値が500であれば不十分(差分:1)、999.9であれば十分(差分:0.0001)に正確と判断する)

計算機プログラムの構造と解釈[第2版]

計算機プログラムの構造と解釈[第2版]