ニュートン法

分からないままに来ていたニュートン法を勉強し直しました
例えば平方根を求める関数を考えた時に
sqrt{x}=y\geq0かつy^2=\ xであるようなy
のように定義出来ます
けれどもこれは数学の関数なので実数を入れても求めたい数が出てこないのです

gosh> (define ( sqrt x )
 (the y ( and ( >= y 0 )
  ( = ( square y ) x ))))
(define ( square y ) ( * y y ))sqrt
gosh> 
square
gosh> ( sqrt 9 )
*** ERROR: unbound variable: y
Stack Trace:

このコードを見ても分かるように数学的記述とプログラミングの記述では
記述方法が異なるのです
この場合はyの値を明確にしてないので処理が出来ないのですね
ではプログラミングで平方根を計算してみる場合はどうするのかと言うと
ニュートン法を使うのです

ニュートン法

数xの平方根の値の予測値yがあった場合yとx/yの平均値を取るという
単純な計算方法で真の平方根に近い予測値が得られる
平方根の予測値(y)+数(x)/平方根の予測値(y)/2
この式で出た新しい予測値を繰り返しyに代入し処理を繰り返す事で
結果より近い近似値が得られます

gosh> ( define ( sqrt-iter guess x)
      ( if ( good-enough? guess x )
    guess
     ( sqrt-iter ( improve guess x)
      x)))
sqrt-iter
gosh>  ( define ( improve guess x )
       ( average guess ( / x guess )))
improve
gosh>  ( define ( average x y )     
       ( / ( + x y ) 2 ))
average
gosh> ( define ( good-enough? guess x )
      ( < ( abs ( - ( square guess ) x )) 0.001 ))
good-enough?
gosh> ( define ( sqrt x )
      (  sqrt-iter 1.0 x ))
sqrt
gosh>  ( define ( square x ) ( * x x ))
square
gosh> ( sqrt 9 )
3.00009155413138
gosh> ( sqrt 2 )
1.4142156862745097
gosh> (sqrt 3 )
1.7321428571428572

忘れたら痛いので特に自分のためにwコード解説w

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

x(数値xの平方根の値)の予測値(guess)をsqrt-iterすると定義する
iter = iteration 繰り返し
sqrt = square root 平方根
もしxの予測値が充分であれば予測値を返し
xの予測値を改善するならxをsqrt-iter(平方根を繰り返し計算)する

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

xの予測値をimproveすると定義する
推測値の平均はx÷guessである

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

xとyの平均値はx+y/2であると定義する

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

xの予測値が充分である?と定義する
予測値の二乗マイナスxの絶対値が0.001より小さい

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

xの平方根を定義する
xは1.0より平方根の計算を繰り返す
1.0と書いてあるのはここで1だと予測値が小数点以下の場合計算出来ないので
注意しないといけません

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

squareはxの二乗だと定義します
以上がこのコードの内容なのですが
私はschemeのコードを読むときとか書くときは

 (define ( 関数名 引数 ) ( 中身 ))

という感じで見ています
まだ簡単なコードとかしか書けないけどschemeのコードをたくさん
書けたらいいな☆