1.3. Формулирование абстракций с помощью процедур высших порядков
79
иметь по крайней мере один ноль на отрезке между a и b . Чтобы найти его, возьмем x,
равное среднему между a и b, и вычислим f(x). Если f (x) > 0, то f должна иметь ноль
на отрезке между a и x. Если f(x) < 0, то f должна и меть ноль на отрезке между x и b.
Продол жая таким образом, мы сможем находить все более узкие интервалы, на которых
f должна иметь ноль. Когда мы дойдем до точки, где этот интервал достаточно мал,
процесс останавливается . Поскольку интервал неопределенности уменьшается вдвое на
каждом шаге процесса, число требуемых шагов растет как Θ(log(L/T )), где L есть длина
исходного интервала, а T есть допуск ошибки (то есть размер интервала, который мы
считаем «достаточно малым»). Вот процедура, которая реализует эту стратегию:
(define (search f neg-point pos-point)
(let ((midpoint (average neg-point pos-point)))
(if (close-enough? neg-point pos-point)
midpoint
(let ((test-value (f midpoint)))
(cond ((positive? test-value)
(search f neg-point midpoint))
((negative? test-value)
(search f midpoint pos-point))
(else midpoint))))))
Мы предполагаем, что вначале нам дается функция f и две точки, в одной из ко-
торых значение функции отрицательно, в другой положительно. Сначала мы вычисляем
среднее между двумя краями интервала. Затем мы проверяем, не является ли интервал
уже достаточно малым, и если да, сразу возвращаем среднюю точку как ответ. Если
нет, мы вычисляем значение f в средней точке. Если э то значение положительно, мы
продолжаем процесс с интервалом от исходной отрицательной точки до средней точки.
Если значение в средней точке отрицательно, мы продолжаем процесс с интервалом от
средней точки до исходной положительной точки. Наконец, существует возможность,
что значение в средней точке в точности равно 0, и тогда средняя точка и есть тот
корень, который мы ищем.
Чтобы проверить, достаточно ли близки концы интервала, мы можем взять проце-
дуру, подобную той, которая используется в разделе 1.1.7 при вычислении квадратных
корней
55
:
(define (close-enough? x y)
(< (abs (- x y)) 0.001))
Использовать процедуру search непосредственно ужасно неудобно, поскольку слу-
чайно мы можем дать ей точки, в ко торых значения f не имеют нужных знаков, и в этом
случае мы получим неправильный о твет. Вместо этого мы будем использовать search
посредством следующей процедуры, которая проверяет, который конец интервала имеет
положительное, а который отрицательное значение, и соответствующим образ ом зовет
55
Мы использовали 0.001 как достаточно «малое» число, чтобы указать допустимую ошибку вычисления.
Подходящий допуск в настоящих вычислениях зависит от решаемой задачи, ограничений компьютера и алго-
ритма. Часто это весьма тонкий вопрос, в котором требуется помощь специалиста по численному анализу или
волшебника какого-нибудь другого рода.