SICP練習1.40~1.46です。プロシージャを返却値にする。
問題
練習1.40 :newtons-method で x^3 + ax^2 + bx + c の零点を求める。
練習1.41 :(((double (double double)) inc) 5) の返却値を求める。
練習1.42 :複合関数を定義する。
練習1.43 :関数の複数適用。
練習1.44:平滑化(smoothing) → 略
練習1.45:n 乗根を求める → 略
練習1.46:反復改良法 → 略
解答
練習1.40の解答
float delegate( float ) deriv( float delegate( float ) g) {
float dg( float x) {
return (g(x + DX) - g(x)) / DX;
}
return &dg;
}
float delegate( float ) newton_transform( float delegate( float ) g) {
float dg( float x) {
return x - g(x) / deriv(g)(x);
}
return &dg;
}
float newtons_method( float delegate( float ) g, float guess) {
return fixedPoint(newton_transform(g), guess);
}
float cubic( float a, float b, float c) {
float g( float x) {
return x * x * x + a * x * x + b * x + c;
}
float root = newtons_method(&g, 1);
return root;
}
float delegate(float) deriv(float delegate(float) g) { float dg(float x) { return (g(x + DX) - g(x)) / DX; } return &dg; } float delegate(float) newton_transform(float delegate(float) g) { float dg(float x) { return x - g(x) / deriv(g)(x); } return &dg; } float newtons_method(float delegate(float) g, float guess) { return fixedPoint(newton_transform(g), guess); } /** * 練習1.40。 * newtons-method で x^3 + ax^2 + bx + c の零点を求める。 */ float cubic(float a, float b, float c) { float g(float x) { return x * x * x + a * x * x + b * x + c; } float root = newtons_method(&g, 1); return root; }
コンパイルは通りましたが、実行時 Stack Overflow エラーが発生していました。ロジックの問題か、D言語の問題か今のところ不明です。分かっている方は教えてください。
練習1.41の解答
(double (double double)) = (2 * 2) * (2 * 2) = 16回、ですから、 解は inc を16回 適用することです。結果は 16 + 5 = 21 でしょう。
練習1.42の解答
int compose( int delegate( int ) f, int delegate( int ) g, int x) {
return f(g(x));
}
/** * 練習1.42。 * 複合関数を定義する。 */ int compose(int delegate(int) f, int delegate(int) g, int x) { return f(g(x)); }
実行結果。
c:\home\sicp>q1_40_q1_46.exe
---- 1.42 ----
compose(square, inc, 6) = 49
練習1.43の解答
int repeated( int delegate( int ) f, int x, int n) {
int result = x;
for ( int i = 0; i < n; i++) {
result = f(result);
}
return result;
}
/** * 練習1.43。 * 関数の重複適用。 */ int repeated(int delegate(int) f, int x, int n) { int result = x; for(int i = 0; i < n; i++) { result = f(result); } return result; }
実行結果。
---- 1.43 ----
repeated(square, 5, 2) = 625