計算機プログラムの構造と解釈 第二版 P44 問題1.45
はい。この問題をやっている間に、HDがぶっ壊れたりして、
そういう意味でかなり難問でした。
この問題解き終える前に勉強会でやっちゃっておいてあるので、悔しい限りです。
以下、本題。
この問題はこんな感じで進めていく。
1.n乗根を計算するときに、何回平均緩和するか指定できる手続きをつくる。
2.n乗根を計算するのに必要な平均緩和の数を実験で求める
3.平均緩和の回数を自動的に求めて計算してくれる手続きをつくる。
そんな感じで、上の「1」は割と簡単にできたん。
こんな感じ
;;root-prototipe (define (root-prototipe x m n) (fixed-point ((repeated average-dump n) (lambda (y) (/ x (expt y (- m 1))))) 1.0))
xが根を求める数。
mが何乗の根か、普通のルートだったら、2
nは何回平均緩和するか。
んで、「2」なんだけど、これ大変。
そんで勉強会では、底が2のログのfloorということになっていて、
それがどういうことかというと、
2乗根・3乗根、平均緩和1回でできる。
4乗根から7乗根、平均緩和2回でできる。
8乗根から15乗根、平均緩和3回できる。
16乗根、、、、 平均緩和4回。
って話だったんだけど、
3回の平均緩和で20乗根までいけてしまった!
ま、、いいや、とりあえず、話のまとまりとしては、
2を底とするn(何乗根か?)の対数の小数点以下を切り捨てたもの
っ手感じなのです。
ひとによっては、「2を底とするって、どうやんだよ!」
ってなりそうなんで、書いておくと、
log n ÷ log 2
って感じですね。
だので、ここは、
(floor (/ (log n) (log 2))
見たいな感じなると思われる。
んでは実装。
#!/usr/local/bin/gosh ;; -*- coding: utf-8 -*- (use ggc.debug.trace) (define (inc x) (+ x 1)) (define (square x) (* x x)) (define (compose f g) (lambda (x) (f (g x)))) ;; fixed-point (define tolerance 0.00001) (define (fixed-point f first-guess) (define (close-enough? v1 v2) (< (abs (- v1 v2)) tolerance)) (define (try guess) (let ((next (f guess))) (if (close-enough? guess next) next (try next)))) (try first-guess)) ;; average-dump (define (average p1 p2) (/ (+ p1 p2) 2)) (define (average-dump f) (lambda (x) (average x (f x)))) ;; repeated (define (repeated f n) (if (= n 1) (lambda (x) (f x)) (repeated (compose f f) (- n 1)))) ;;root-prototype (define (root-prototype x m n) (fixed-point ((repeated average-dump n) (lambda (y) (/ x (expt y (- m 1))))) 1.0)) ;;root (define (root x m) (fixed-point ((repeated average-dump (floor (/ (log m) (log 2)))) (lambda (y) (/ x (expt y (- m 1))))) 1.0)) ;; main (define (main args) (display "1回平均緩和")(newline) (display "(root-prototype ")(display (expt 3 2))(display " 2 1) : ") (display (root-prototype 9 2 1))(newline) (display "(root-prototype ")(display (expt 3 3))(display " 3 1) : ") (display (root-prototype 27 3 1))(newline) (display "2回平均緩和")(newline) (display "(root-prototype ")(display (expt 3 4))(display " 4 2) : ") (display (root-prototype (expt 3 4) 4 2))(newline) (display "(root-prototype ")(display (expt 3 5))(display " 5 2) : ") (display (root-prototype (expt 3 5) 5 2))(newline) (display "(root-prototype ")(display (expt 3 6))(display " 6 2) : ") (display (root-prototype (expt 3 6) 6 2))(newline) (display "(root-prototype ")(display (expt 3 7))(display " 7 2) : ") (display (root-prototype (expt 3 7) 7 2))(newline) (display "3回平均緩和")(newline) (display "(root-prototype ")(display (expt 3 8))(display " 8 3) : ") (display (root-prototype (expt 3 8) 8 3))(newline) (display "(root-prototype ")(display (expt 3 9))(display " 9 3) : ") (display (root-prototype (expt 3 9) 9 3))(newline) (display "(root-prototype ")(display (expt 3 10))(display " 10 3) : ") (display (root-prototype (expt 3 10) 10 3))(newline) (display "(root-prototype ")(display (expt 3 11))(display " 11 3) : ") (display (root-prototype (expt 3 11) 11 3))(newline) (display "(root-prototype ")(display (expt 3 12))(display " 12 3) : ") (display (root-prototype (expt 3 12) 12 3))(newline) (display "(root-prototype ")(display (expt 3 13))(display " 13 3) : ") (display (root-prototype (expt 3 13) 13 3))(newline) (display "(root-prototype ")(display (expt 3 14))(display " 14 3) : ") (display (root-prototype (expt 3 14) 14 3))(newline) (display "(root-prototype ")(display (expt 3 15))(display " 15 3) : ") (display (root-prototype (expt 3 15) 15 3))(newline) (display "3回平均緩和")(newline) (display "(root-prototype ")(display (expt 3 16))(display " 16 4) : ") (display (root-prototype (expt 3 16) 16 4))(newline) (newline) (display "Mission complete!!!")(newline) (display "(root ")(display (expt 3 16))(display " 16) : ") (display (root (expt 3 16) 16))(newline) (newline) 0)
実行!!
1回平均緩和 (root-prototype 9 2 1) : 3.0 (root-prototype 27 3 1) : 2.9999972321057697 2回平均緩和 (root-prototype 81 4 2) : 3.000000000000033 (root-prototype 243 5 2) : 3.0000008877496294 (root-prototype 729 6 2) : 2.999996785898161 (root-prototype 2187 7 2) : 3.0000041735235943 3回平均緩和 (root-prototype 6561 8 3) : 3.000007243280675 (root-prototype 19683 9 3) : 3.000004241187395 (root-prototype 59049 10 3) : 3.000003467126666 (root-prototype 177147 11 3) : 3.0000041664726727 (root-prototype 531441 12 3) : 3.000002000091472 (root-prototype 1594323 13 3) : 3.000000991913267 (root-prototype 4782969 14 3) : 3.000000466097833 (root-prototype 14348907 15 3) : 3.000000148387647 3回平均緩和 (root-prototype 43046721 16 4) : 3.0001418216956885 Mission complete!!! (root 43046721 16) : 3.0001418216956885