2008年11月22日 (土)
「プログラミングGauche」読書会#5 お疲れ様でした
主催が、寝坊してすみませんでした。
今回は、第13章〜第16章を読むことができました。次回は第17章、第18章の重そうな章に突入します。次回、次々回がコアな回で楽しめるのではないかと思います。
次回は12/13に予定しております。 次回は、最初に暖房をお願いするようにしたいと思います。
寮にルータとタップを忘れてしまったため、実家の無線LANルータをぱくってきたのでネットワークの設定に時間もかかってしまいました。
「Kaprs」ともどもよろしくお願いいたします。
なお、12/7 には Kansai.AR#1も開催されます!参加者はそろそろ上限に達しそうとのことですが、発表者は絶賛募集中と言うことです。
SICP勉強会#5 ログ
1.36
途中経過を出力する fixed-point
(define tolerance 0.000001)
(define (average x y) (/ (+ x y) 2))
(define (close-enough? x y) (< (abs (- x y)) 0.0001))
(define (fixed-point f first-guess)
(define (close-enough? v1 v2)
(< (abs (- v1 v2)) tolerance))
(define (try guess)
(let ((next (f guess)))
(display guess)
(newline)
(if (close-enough? guess next)
next
(try next))))
(try first-guess))
黄金比
> (fixed-point (lambda (y) (average y (+ 1 (/ 1 y)))) 1.0) 1.0 1.5 1.5833333333333333 1.6074561403508771 1.6147785476652068 1.61702925556443 1.617723628348796 1.6179380934832117 1.6180043565683029 1.6180248320058461 1.6180311591702674 1.618033114362648 1.618033718549466
x^x == 1000 の平均を使う版
> (fixed-point (lambda (y) (average y (/ (log 1000) (log y)))) 0.5) 1> 0.5 2> -4.7328921423310435 3> -1.9294367464856617-0.8831605544952358i 4> -0.6367404417038983+0.7408451809785208i 5> -0.33390127567646233-1.1437670056900082i 6> 0.007399706701754605+1.2737412375384936i 7> 0.3369697820779475-1.5185687703971407i 8> 0.9223014102315796+1.548287537124875i 9> 1.8986842272540216-1.7484010483951409i 10> 3.203369020863236+0.8949152458920809i 11> 4.335196566268348-0.17218050758326126i (snip) 19> 4.555535557172372-8.920402326580877e-8i
x^x == 1000 の平均を使わない版,
> (fixed-point (lambda (y) (/ (log 1000) (log y))) 0.5)) 1> 0.5 2> -9.965784284662087 3> 1.0479216829770386-1.4318909598643041i 4> 3.2721632144996313+5.358070758799561i 5> 2.87075534145715-1.5979029081330443i 6> 4.911698079655922+2.097221141263437i 7> 3.897044834247144-0.9386983476898267i 8> 4.555511086354771-5.173344975628601e-5i (snip) 43> 4.555535538588542-3.5011025728274154e-7i
1.37
再帰版のつもり
これでいいのかなぁ?
(define (cont-frac n d k)
(define (cont-frac-helper n d k j)
(if (= k 0)
(/ (n j) (d j))
(/ (n j) (+ (d j) (cont-frac-helper n d (- k 1) (+ j 1))))))
(cont-frac-helper n d k 0))
反復版のつもり
(define (cont-frac n d k)
(define (cont-frac-iter n d k acc)
(if (= k 0)
acc
(cont-frac-iter n d (- k 1) (/ (n k) (+ (d k) acc)))))
(cont-frac-iter n d k 1))
実行結果
> (cont-frac (lambda (i) 1.0) (lambda (i) 1.0) 100) 0.6180339887498948
といった感じ
> (cont-frac (lambda (i) 1.0) (lambda (i) 1.0) 8) 0.6181818181818182 > (cont-frac (lambda (i) 1.0) (lambda (i) 1.0) 9) 0.6179775280898876
となるので,小数点以下4桁の精度にはk=9かな?(小数点以下5桁で四捨五入すると 0.6180)
1.38
1 2 1 1 4 1 1 6 1 1 8 1 ... を生成する式として
(lambda (i) (if (= (modulo i 3) 2)
(* 2 (+ 1 (quotient i 3)))
1))
を用いた
> (+ 2.0 (cont-frac (lambda (i) 1.0)
(lambda (i) (if (= (modulo i 3) 2)
(* 2 (+ 1 (quotient i 3)))
1))
20))
2.7182818284590455
ちなみに,有理数を使うと
> (exact->inexact (+ 2 (cont-frac (lambda (i) 1)
(lambda (i) (if (= (modulo i 3) 2)
(* 2 (+ 1 (quotient i 3)))
1))
20)))
2.718281828459045
いずれも,Wikipedia に示されている値と,小数点以下15桁まで一致する.
1.39
最初の一項目を特別扱いして,残りを連分数で表した.
(define (tan-cf x k) (/ x (+ 1 (cont-frac (lambda (i) (* (- x) x))
(lambda (i) (+ (* 2 i) 1))
(- k 1)))))
検算は以下のように行った
(define (check-tan x)
(display (tan x))
(newline)
(display (tan-cf x 10)))
> (check-tan 0)
0.0
0#<undef>
> (check-tan 3.14)
-0.001592654936407223
-0.001592660421047437#<undef>
> (check-tan (/ 3.14 6))
0.5769964003928729
0.576996400392872
[]




1.37で、kの次数の順序が逆。再帰(降順)、反復(昇順)。 <br>1.38を「1.37の再帰」で計算すると、「1.37の反復」の場合と食い違い。
検証ありがとうございます。 <br>推測ですが、再帰版のつもりとしていた方が妖しいのだと思われます。