Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Инстр_Mathem_v8.doc
Скачиваний:
4
Добавлен:
16.11.2019
Размер:
1.91 Mб
Скачать

14.5. Повторное выполнение операций

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

Оператор NestList[f, expr, n] – выдает список, который включает исходное выражение expr и результаты n-кратного применения к этому выражению функции f. Функция Nest[f, expr, n] – выдает только последний элемент этого списка.

Пример 14.10

In[ ] := NestList[f, x, 3] Out[ ] = {x, f[x], f[f[x]], f[f[f[x]]]}

Пример 14.11

Составим программу для решения методом Эйлера задачи Коши для дифференциального уравнения y’(x) = f(x, y) c начальным условием y(x0) = y0. Введем на оси x сетку: xi = x0 + h*i, где h – шаг приращения аргумента x. В соответствии с методом Эйлера формула для последовательного вычисления значений y в узлах сетки имеет вид: yi+1 = yi + h*f(xi, yi).

In[ ] := E2[f_, x0_, y0_, h_, n_] := Module[{w},

w[{x_, y_}] = {x+h, y+h*f[x, y]}; NestList[w, {x0, y0}, n]]

Обратим внимание, что функция w является векторной функцией.

Найдем решение уравнения y’(x) = y с начальным условием y(0)=1:

In[ ] := f[x_, y_] = y; E2[f, 0, 1, 0.05, 3]

Out[ ] = {{0, 1}, {0.05, 1.05}, {0.1, 1.1025}, {0.15, 1.15763}}

Элементы этого списка содержат значения x и y в узлах сетки с шагом 0.05. Точное решение данной задачи Коши представляет собой экспоненту: y(x) = ex. Сравним найденное приближенное решение с точным:

In[ ] := Table[{x, Exp[x]}, {x, 0, 0.15, 0.05}]

Out[ ] = {{0, 1}, {0.05, 1.05127}, {0.1, 1.10517}, {0.15, 1.16183}}

Оператор FixedPointList[f, expr] – генерирует список результатов повторного применения функции f к выражению expr. Список начинается с выражения expr и заканчивается, когда результаты повторного применения f перестают изменяться (в пределах точности, обеспечиваемой компьютером). FixedPoint[f, expr] – выдает только последний элемент списка.

Пример 14.12

Создадим функцию для вычисления квадратного корня числа x с помощью итерационного процесса Герона (один из вариантов такой функции приведен в разделе 8, пример 8.10):

In[ ] := r2[x_] := Module[{f}, f[v_] = (v+ x / v) / 2; FixedPoint[f, x+1.]]

В программе задается начальное значение x+1, которое затем уточняется в процессе последовательных итераций – повторном применении функции f. Например, найдем значение квадратного корня из двух:

In[ ] := r2[2] Out[ ] = 1.41421

Оператор NestWhileList[f, x, test] – генерирует список {x, f[x], f[f[x]], …}; процесс генерации заканчивается, когда перестает выполняться условие test.

NestWhileList[f, x, test, m] – в качестве аргументов условия test используются m последних результатов применения функции f.

NestWhile[…] – выдает только последний элемент списка.

14.6. Анонимные функции

Анонимные функции – это функции без имени. В ряде случаев функции вводятся только для однократного использования. Например, таковы локальные функции, входящие в конструкцию Module. Если функция используется только один раз, то она и не нуждается в имени. Синтаксис анонимной функции: body &, – тело функции, заканчивающееся знаком амперсенд &. Формальными аргументами анонимной функции служат # или #1, #2, #3, … Знак & является обязательным элементом, указывающим, что данное выражение является определением анонимной функции. Амперсенд имеет самый низкий приоритет, поэтому в выражениях типа #1+#2 & тело функции не требуется заключать в скобки. С другой стороны, если анонимная функция служит правой частью выражения, то вся она должна быть взята в скобки, например: option -> (body &).

Пример 14.13

Запишем выражение, содержащее два вхождения функции Sin, а затем заменим в этом выражении Sin на возведение в квадрат:

In[ ] := {b = Sin[a + Sin[2x]], b/.Sin->(#^2 &)} Out[ ] = {Sin[a = Sin[2x]], (a + 4 x2)2}

Использование анонимных функций совместно с операциями циклической обработки выражений позволяет создавать очень компактные программы.

Пример14.14

Вычисление квадратного корня с помощью процесса Герона (см. примеры 8.10, 14.12):

In[ ] := r3[x_] := FixedPoint[(# + x / #) / 2 &, x+1.]; r3[2] Out[ ] = 1.41421

Пример14.15

Нахождение корня уравнения f(x)=0 с помощью итерационного метода Ньютона. Алгоритм Ньютона описывается формулой: xi+1 = xif(xi) / f’(xi), где xi – значение корня, полученное на i-ом шаге итераций. Задав подходящее начальное значение x0,можно найти значение корня с требуемой точностью. Опишем алгоритм Ньютона с использованием циклической операции FixedPoint:

In[ ] := Newt[f_, x0_] := FixedPoint[# - f[#] / f’[#] &, x0]

Здесь x0 – начальное приближение. Данная программа позволяет найти корень уравнения уравнения f(x)=0 с точностью, которую обеспечивает математический сопроцессор.

Использование циклической операции NestWhile позволяет найти корень уравнения с заданной точностью:

In[ ] := Newt2[f_, x0_, eps_] := NestWhile[# - f[#] / f’[#] &, x0, Abs[#1 - #2] > eps &, 2]

Итерационный процесс, описываемый данной программой, заканчивается, если два последних значения отличаются не более, чем на eps.

Найдем положительный корень уравнения x3+x-1=0 с точностью 10-5:

In[ ] := f [x_] = x^3+x-1.; Newt2[f, 1., 10^-5] Out[ ] = 0.682328

Пример14.16

Вычисление “машинного эпсилон” (см. также примеры 7.1 и 7.2):

In[ ] := NestWhile[# / 2. &, 1., # + 1. > 1. &]*2 Out[ ] = 2.84212*10-14