
- •5. Применение функционалов
- •5.1 Функционалы работы со списками
- •5.1.1 Функции свертки fold, foldr и foldl
- •5.1.2 Отображающая функция map
- •5.1.3 Функция фильтрования filter
- •5.2 Функционал символьного дифференцирования
- •5.3 Элементы систем упрощения алгебраических выражений
- •5.4 Применение символьных функционалов
5.4 Применение символьных функционалов
Объединим символьное дифференцирование с численными вычислениями, т.е., используем процедуру дифференцирования вместе с процедурой решения уравнений методом Ньютона. Но для этого необходимо вычислить значения функций, определяемых символьными выражениями.
Напишем процедуру expr->fun, преобразующую символьное выражение в функцию. Она будет состоять из реализации двух мыслей.
Сначала необходимо записать исходное выражение как лямбда-выражение и затем применить к построенному S-выражению замечательную функцию eval, чтобы получить численное значение символьного выражения.
> (define (expr->fun var expr)
(eval (list 'lambda (list var) expr)))
Пример работы
> ((expr->fun 'x '(- 2 (* x x))) 3)
-7
Теперь мы можем написать новую процедуру для метода Ньютона.
Она должна имееть три аргумента: expr - выражение, которое определяет функцию,
var - имя переменной и
начальное приближение x.
С помощью diff происходит символьное дифференцирование исходного выражения по переменной var, далее исходное выражение и его производная преобразуются в численные значения функций, а затем использует численный метод newton-method для решения уравнения.
> (define (newton-method-smart expr var x)
(newton-method (expr->fun var expr) ;сама функция
(expr->fun var (diff expr var)) ;ее призводная
x))
Вспомним, как мы раньше определяли newton-method
> (define err 0.00001)
> (define (near? x1 x2)
(< (abs (- x1 x2)) err))
> (define (newton-method f df s)
(define (improve x)
(- x (/ (f x) (df x))) )
(define (newton-iter x)
(let ((y (improve x)))
(if (near? y x) y
(newton-iter y))))
(newton-iter s) )
Наше
выражение имеет вид
И тогда мы определим вычисление
квадратного корня, обращаясь к
символьно-численному методу так:
> (define (sqrt5 a)
(newton-method-smart (list '- a '(* x x)) 'x 1))
Давайте посмотрим, как теперь происходит вычисление.
> (sqrt5 2)
(что есть = 1,4142135623746899)
Обратим внимание на рациональное число в ответе. И для сравнения точности
> (sqrt 2)
1.4142135623730951
Конечно, реальную пользу такой подход может принести в тех случаях, когда уравнение слишком сложно для ручного дифференцирования.
Page