Ремонт принтеров, сканнеров, факсов и остальной офисной техники


назад Оглавление вперед




[21]

(define ((имя) a b)

(if (> a b) 0

(+ ((терм) a)

((имя) ((следующий) a) b))))

Присутствие такого общего шаблона является веским доводом в пользу того, что здесь скрыта полезная абстракция, которую только надо вытащить на поверхность. Действительно, математики давно выделили абстракцию суммирования последовательности (summation of a series) и изобрели «сигма-запись», например

b

£f (n) = f (а) + ... + f (b)

n=a

чтобы выразить это понятие. Сила сигма-записи состоит в том, что она позволяет математикам работать с самим понятием суммы, а не просто с конкретными суммами - например, формулировать общие утверждения о суммах, независимые от конкретных суммируемых последовательностей.

Подобным образом, мы как проектировщики программ хотели бы, чтобы наш язык был достаточно мощным и позволял написать процедуру, которая выражала бы само понятие суммы, а не только процедуры, вычисляющие конкретные суммы. В нашем процедурном языке мы можем без труда это сделать, взяв приведенный выше шаблон и преобразовав «дырки» в формальные параметры:

(define (sum term a next b)

(if (> a b) 0

(+ (term a)

(sum term (next a) next b))))

Заметьте, что sum принимает в качестве аргументов как нижнюю и верхнюю границы a и b, так и процедуры term и next. Sum можно использовать так, как мы использовали бы любую другую процедуру. Например, с ее помощью (вместе с процедурой inc, которая увеличивает свой аргумент на 1), мы можем определить sum-cubes:

(define (inc n) (+ n 1))

(define (sum-cubes a b) (sum cube a inc b))

Воспользовавшись этим определением, мы можем вычислить сумму кубов чисел от 1 до 10:

(sum-cubes 1 10) 3025

С помощью процедуры идентичности (которая просто возвращает свой аргумент) для вычисления терма, мы можем определить sum-integers через sum:


(define (identity x) x)

(define (sum-integers a b) (sum identity a inc b))

Теперь можно сложить целые числа от 1 до 10:

(sum-integers 1 10) 55

Таким же образом определяется pi-sum: 50

(define (pi-sum a b) (define (pi-term x)

(/ 1.0 (* x (+ x 2))))

(define (pi-next x)

(+ x 4))

(sum pi-term a pi-next b)) С помощью этих процедур мы можем вычислить приближение к п:

(* 8 (pi-sum 1 1000)) 3.139592655589783

Теперь, когда у нас есть sum, ее можно использовать в качестве строительного блока при формулировании других понятий. Например, определенный интеграл функции f между пределами а и b можно численно оценить с помощью формулы

Ja f = f (а + y) + f [a + dx + y) + / + 2dx + y) + dx

для малых значений dx. Мы можем прямо выразить это в виде процедуры:

(define (integral f a b dx) (define (add-dx x) (+ x dx)) (* (sum f (+ a (/ dx 2)) add-dx b)

dx))

(integral cube 0 1 0.01)

.24998750000000042

(integral cube 0 1 0.001)

.249999875000001

(Точное значение интеграла cube от 0 до 1 равно 1/4.)

Упражнение 1.29.

Правило Симпсона - более точный метод численного интегрирования, чем представленный выше. С помощью правила Симпсона интеграл функции f между а и b приближенно вычисляется в виде

50Обратите внимание, что мы использовали блочную структуру (раздел 1.1.8), чтобы спрятать определения pi-next и pi-term внутри pi-sum, поскольку вряд ли эти процедуры понадобятся зачем-либо еще. В разделе 1.3.2 мы совсем от них избавимся.


g [уо + Ц)\ + 2у2 + 4у3+2у4 + ...+ 2уп-2 + 4j/„ i + уп]

где h = (b - а)/п, для какого-то четного целого числа п, а yk = f (а+kh). (Увеличение п повышает точность приближенного вычисления.) Определите процедуру, которая принимает в качестве аргументов f, а, b и п, и возвращает значение интеграла, вычисленное по правилу Симпсона. С помощью этой процедуры проинтегрируйте cube между 0 и 1 (с п = 100 и п = 1000) и сравните результаты с процедурой integral, приведенной выше.

Упражнение 1.30.

Процедура sum порождает линейную рекурсию. Ее можно переписать так, чтобы суммирование выполнялось итеративно. Покажите, как сделать это, заполнив пропущенные выражения в следующем определении:

(define (sum term a next b) (define (iter a result) (if (??) (??)

(iter (??) (??))))

(iter (??) (??)))

Упражнение 1.31.

a.Процедура sum - всего лишь простейшая из обширного множества подобных абстракций, которые можно выразить через процедуры высших порядков.51 Напишите аналогичную процедуру под названием product, которая вычисляет произведение значений функции в точках на указанном интервале. Покажите, как с помощью этой процедуры определить factorial. Кроме того, при помощи product вычислите приближенное значение п по формуле52

7г 2 • 4 • 4 • 6 • 6 • 8 • • • 4 ~ 3-3-5-5-7-7---

b.Если Ваша процедура product порождает рекурсивный процесс, перепишите ее так, чтобы она порождала итеративный. Если она порождает итеративный процесс, перепишите ее так, чтобы она порождала рекурсивный.

Упражнение 1.32.

a. Покажите, что sum и product (упражнение 1.31) являются частными случаями еще более общего понятия, называемого накопление (accumulation), которое комбинирует множество термов с помощью некоторой общей функции накопления

(accumulate combiner null-value term a next b)

51 Смысл упражнений 1.31-1.33 состоит в том, чтобы продемонстрировать выразительную мощь, получаемую, когда с помощью подходящей абстракции обобщается множество операций, казалось бы, не связанных между собой. Однако, хотя накопление и фильтрация - изящные приемы, при их использовании руки у нас пока что несколько связаны, поскольку пока что у нас нет структур данных, которые дают подходящие к этим абстракциям средства комбинирования. В разделе 2.2.3 мы вернемся к этим приемам и покажем, как использовать последовательности (sequences) в качестве интерфейсов для комбинирования фильтров и накопителей, так что получаются еще более мощные абстракции. Мы увидим, как эти методы сами по себе становятся мощным и изящным подходом к проектированию программ.

52Эту формулу открыл английский математик семнадцатого века Джон Уоллис.



[стр.Начало] [стр.1] [стр.2] [стр.3] [стр.4] [стр.5] [стр.6] [стр.7] [стр.8] [стр.9] [стр.10] [стр.11] [стр.12] [стр.13] [стр.14] [стр.15] [стр.16] [стр.17] [стр.18] [стр.19] [стр.20] [стр.21] [стр.22] [стр.23] [стр.24] [стр.25] [стр.26] [стр.27] [стр.28] [стр.29] [стр.30] [стр.31] [стр.32] [стр.33] [стр.34] [стр.35] [стр.36] [стр.37] [стр.38] [стр.39] [стр.40] [стр.41] [стр.42] [стр.43] [стр.44] [стр.45] [стр.46] [стр.47] [стр.48] [стр.49] [стр.50] [стр.51] [стр.52] [стр.53] [стр.54] [стр.55] [стр.56] [стр.57] [стр.58] [стр.59] [стр.60] [стр.61] [стр.62] [стр.63] [стр.64] [стр.65] [стр.66] [стр.67] [стр.68] [стр.69] [стр.70] [стр.71] [стр.72] [стр.73] [стр.74] [стр.75] [стр.76] [стр.77] [стр.78] [стр.79] [стр.80] [стр.81] [стр.82] [стр.83] [стр.84] [стр.85] [стр.86] [стр.87] [стр.88] [стр.89] [стр.90] [стр.91] [стр.92] [стр.93] [стр.94] [стр.95] [стр.96] [стр.97] [стр.98] [стр.99] [стр.100] [стр.101] [стр.102] [стр.103] [стр.104] [стр.105] [стр.106] [стр.107] [стр.108] [стр.109] [стр.110] [стр.111] [стр.112] [стр.113] [стр.114] [стр.115] [стр.116] [стр.117] [стр.118] [стр.119] [стр.120] [стр.121] [стр.122] [стр.123] [стр.124] [стр.125] [стр.126] [стр.127] [стр.128] [стр.129] [стр.130] [стр.131] [стр.132] [стр.133] [стр.134] [стр.135] [стр.136] [стр.137] [стр.138] [стр.139] [стр.140] [стр.141] [стр.142] [стр.143] [стр.144] [стр.145] [стр.146] [стр.147] [стр.148] [стр.149] [стр.150] [стр.151] [стр.152] [стр.153] [стр.154] [стр.155] [стр.156] [стр.157] [стр.158] [стр.159] [стр.160] [стр.161] [стр.162] [стр.163] [стр.164] [стр.165] [стр.166] [стр.167] [стр.168] [стр.169] [стр.170] [стр.171] [стр.172] [стр.173] [стр.174] [стр.175] [стр.176] [стр.177] [стр.178] [стр.179] [стр.180] [стр.181] [стр.182] [стр.183] [стр.184] [стр.185] [стр.186] [стр.187] [стр.188] [стр.189] [стр.190] [стр.191] [стр.192] [стр.193] [стр.194] [стр.195] [стр.196]