プロシジャーを引数にする(delegate)。
問題
練習1.29:Simpson’s ruleで積分を求める。
練習1.30:Sumの反復版。
練習1.31:再帰と反復でπを求める。
練習1.32と1.33を略します。
解答
練習1.29の解答
-
-
-
-
- float simpson(float delegate(float x) f, float a, float b, int n) {
- float h = (b - a) / n;
- float y(int k) {
- return f(a + k * h);
- }
-
- float ret = y(0);
- for (int i = 1; i < n; i++) {
- if (i % 2 == 0) {
- ret += 2 * y(i);
- } else {
- ret += 4 * y(i);
- }
- }
- ret += y(n);
- return (h / 3) * ret;
- }
-
-
- void main() {
- float cube(float x) {
- return x * x * x;
- }
-
- float ret;
- ret = simpson(&cube, 0, 1, 100);
- Stdout.formatln("simpson(cube, 0, 1, 100) = {0:d16}", ret);
-
- ret = simpson(&cube, 0, 1, 1000);
- Stdout.formatln("simpson(cube, 0, 1, 1000) = {0:d16}", ret);
- }
/** * 練習1.29。 * Simpson’s ruleで積分を求める。 */ float simpson(float delegate(float x) f, float a, float b, int n) { float h = (b - a) / n; float y(int k) { return f(a + k * h); } float ret = y(0); for (int i = 1; i < n; i++) { if (i % 2 == 0) { ret += 2 * y(i); } else { ret += 4 * y(i); } } ret += y(n); return (h / 3) * ret; } void main() { float cube(float x) { return x * x * x; } float ret; ret = simpson(&cube, 0, 1, 100); Stdout.formatln("simpson(cube, 0, 1, 100) = {0:d16}", ret); ret = simpson(&cube, 0, 1, 1000); Stdout.formatln("simpson(cube, 0, 1, 1000) = {0:d16}", ret); }
実行結果。
simpson(cube, 0, 1, 100) = 0.2500000000000000
simpson(cube, 0, 1, 1000) = 0.2500000894069672
|
n が大きい時精度が高いはずですが、逆に落ちています(精確値が 0.25)。何故か分からないです。分かる方でございましたら、教えてください。
練習1.30の解答
(define (sum term a next b)
(define (iter a result)
(if > a b)
result
(iter (next a) (+ result (term a)))))
(iter a 0))
練習1.31の解答
-
-
-
-
- static float term(int n) {
- if (n == 2) {
- return 2f / 3f;
- }
- float x = cast(float) n;
- return (x / (x - 1)) * (x / (x + 1));
- }
-
- static int next(int k) {
- return k + 2;
- }
-
-
- float product(float function(int n) term, int function(int k) next, int a, int b) {
- if (a > b) {
- return 1f;
- }
- return term(a) * product(term, next, next(a), b);
- }
-
- float pi(int n) {
-
- return 4 * product(&term, &next, 2, n);
- }
-
-
- float product2(float function(int n) term, int function(int k) next, int a, int b) {
-
- float iter(int a, float result) {
- if (a > b) {
- return result;
- }
- return iter(next(a), term(a) * result);
- }
-
- return iter(a, 1);
- }
-
- float pi2(int n) {
- return 4 * product2(&term, &next, 2, n);
- }
/** * 練習1.31。 * 再帰と反復でπを求める。 */ static float term(int n) { if (n == 2) { return 2f / 3f; } float x = cast(float) n; return (x / (x - 1)) * (x / (x + 1)); } static int next(int k) { return k + 2; } // 再帰版 float product(float function(int n) term, int function(int k) next, int a, int b) { if (a > b) { return 1f; } return term(a) * product(term, next, next(a), b); } float pi(int n) { // n is even number return 4 * product(&term, &next, 2, n); } // 反復版 float product2(float function(int n) term, int function(int k) next, int a, int b) { float iter(int a, float result) { if (a > b) { return result; } return iter(next(a), term(a) * result); } return iter(a, 1); } float pi2(int n) { return 4 * product2(&term, &next, 2, n); }
実行結果。
---- 1.31 ----
pi(10) = 3.0021762847900391
pi(100) = 3.1260795593261719
pi(1000) = 3.1400253772735596
pi(10000) = 3.1412661075592041
--------
pi2(10) = 3.0021758079528809
pi2(100) = 3.1260778903961182
pi2(1000) = 3.1400227546691895
pi2(10000) = 3.1413297653198242 |
|