Решение упражнения 1.29 из SICP
Итак, мы переходим к упражнениям раздела 1.3, в котором речь идет о процедурах высших порядков. Поддержка процедур высших порядков и вообще работа с процедурами как с данными является очень мощным средством построения абстракций. В упражнениях мы как раз этими абстракциями и займемся.
Реализация формулы Симпсона для вычисления определенного интеграла выглядит следующим образом:
(define (simpson f a b n) (define h (/ (- b a) n)) (define (g k) (define (c k) (cond ((= k 0) 1) ((= k n) 1) ((even? k) 2) (else 4))) (* (c k) (f (+ a (* k h))))) (define (inc k) (+ k 1)) (/ (* (sum g 0 inc n) h) 3))
Заметим, что мы переиспользовали процедуру sum, которая задает схему вычислений, в которую можно уложить и метод Симпсона.
Интегрируя с помощью этой процедуры функцию f(x)=x3 между 0 и 1 с n=100 и n=1000, получим:
> (simpson cube 0 1 100) 1/4 > (simpson cube 0 1 1000) 1/4
То есть видно, что формула Симпсона дает более точный результат, чем формула центральных прямоугольников, использовавшаяся в процедуре integral из основного текста раздела.
Comments
Comment from thror
Date: February 14, 2008, 11:59 pm
Все, у кого не встречал используют формулу Симпсона так… А я использую всегда так. Обратите внимание—корректность определения сохраняется, а чередование коэффициентов получается само собой
(define (simpson f a b n)
(let ((h (/ (- b a) n)))
(/ (* h (sum (lambda (x) (+ (f (- x h)) (* 4 (f x)) (f (+ x h))))
(+ a h)
(lambda (x) (+ x h h))
b))
3)))
–thror
Comment from Sergey Khenkin
Date: February 15, 2008, 9:55 am
А я когда-то встречал и такой вариант тоже.
Я думаю, дело в том, что авторы подводят все формулы под один вид ∑i=1..n ci f(xi) и записывают определение ci, i=1..n отдельно.
Comment from Sergey Khenkin
Date: February 15, 2008, 10:05 am
Возможно, еще одним основанием для использования формулы именно в классическом виде является то, что при этом интегрируемая функция в кажой точке вычисляется ровно один раз (что может быть важно в плане эффективности для сложных функций). В предложенном же варианте функция в среднем вычисляется 1.5 раза в каждой точке.
Мне, кстати, очень нравится такая короткая запись. Симпатично выглядит.
Comment from gorilych
Date: July 15, 2008, 5:19 am
Как вариант:
(define (simpson f a b n)
(define h (/ (- b a) n))
(define dx (* 2 h))
(define (next x) (+ x dx))
(* (/ h 3)
(+ (f a)
(f b)
(* 2 (sum f (+ a dx) next (- b dx)))
(* 4 (sum f (+ a h) next (- b h))))))
Кроме того, формула Симпсона использует кубическое приближение, поэтому в данном случае интегрирования кубической функции не просто “более точный результат” а именно _точный_ результат. В чём можно убедиться, используя n = 2:
1 ]=> (simpson cube 0 1 2)
;Value: 1/4
Comment from psv
Date: March 19, 2009, 12:11 am
полученный алгоритм имеет какие то специэффекты
(define (integral-simps f a b n)
(define h (/ (- b a) n))
(define (step2 x) (+ x h h))
(/ (* h
(+ (f a)
(f b)
(* 2. (sum f (+ a h h) step2 (- b h h)))
(* 4. (sum f (+ a h) step2 (- b h)))))
3.))
guile> (integral-simps cube 0. 1. 60)
0.218833847736626
guile> (integral-simps cube 0. 1. 70)
0.249999999999999
guile> (integral-simps cube 0. 1. 72)
0.249999999999999
guile> (integral-simps cube 0. 1. 74)
0.249999999999999
guile> (integral-simps cube 0. 1. 76)
0.22504211555825
Write a comment