Процедуры: подключение к работе
циклов и логики
Возможно, уже понятно, что циклы и логика – мутное дело. Они занимают много места на рабочем листе, и повторная работа с ними требует дополнительных действий, например, курсором. Эти действия можно автоматизировать, поместив их в нечто, что работает как функция, а вам останется только задавать ей значения и получать ответ. Такая структура вызывается командой proc.
Вот пример написания процедуры:
- restart;
Присвоение процедуре имени и определение списка ее аргументов:
- f:=proc(x,y)
Объявление имен локальных переменных, которые используются только внутри процедуры:
- local a,b,z;
Объявление глобальных переменных, которые, будучи объявлены вне процедуры, нужны для использования внутри нее:
- global d;
В данном случае для расчета значения функции f используются переменные:
- локальные a и b,
- глобальная d,
- параметры процедуры x и y,
- локальная переменная z, в которую поместим результат вычислений.
В процедуре Maple возвращаемая велична –
это последняя величина,
вычисляемая в теле этой процедуры.
- a:=3.;b:=17.;
- z:=a*b*x*y*d; # last value
- end;
Дадим значение глобальной переменной d:
- d:=31.;
- f(1,2);
Для иллюстрации работы процедуры показано вычисление косинуса угла в градусах.
- restart;
- cosdeg:=proc(theta)
- local phi,answer;
- phi:=theta*Pi/180.;
- answer:=cos(phi);
- end;
Проверим:
- yy:=cosdeg(45.);
Процедура – это написанная вами программа, поэтому случается (часто), что она не работает. Для отслеживания ошибок придется смотреть, что происходит внутри процедуры, с помощью команды trace.
- trace(cosdeg);
И затем для сравнения результата с известным заранее значением выполните:
- cosdeg(45);
Когда все заработает правильно и вам уже не понадобятся промежуточные данные, напишите:
- untrace(cosdeg);
Исправим процедуру cosdeg так, чтобы она возвращала число с плавающей запятой. Удостоверьтесь, что исправления есть только внутри процедуры, а не в вызове ее из программы.
Если посмотрите на новую процедуру cosdeg, увидите, что она применяется в точности как функция. Но поскольку это самостоятельная программа, она может быть достаточно сложной. Именно поэтому пишутся собственные процедуры. Следует внимательно следить, чтобы определенная таким способом функция не пересекалась с именами команд Maple. Кроме того, следует помнить, что собственные процедуры работают медленнее, чем «родные» команды Maple.
Напишите процедуру, вычисляющую кубический β-сплайн. Выше говорилось, что piecewise работает лучше, чем команды if, но здесь if будет работать отлично, поскольку все помещается внутрь собственной процедуры. Для доказательства не используйте в этой задаче piecewise. Нарисуйте график в интервале –3..3. Заметьте, что возвращаемый ответ должен быть последним результатом процедуры, чтобы его можно было нарисовать. Внутрь процедуры передаются только независимые переменные. То есть для одномерной функции следует использовать B:=proc(x), для двумерной – C:=proc(x,y) и т. д. При рисовании результат процедуры рассматривается как функция и применяется команда plot(f(x),x=a..b) или используется оператор Maple, в котором нет упоминания х: plot(B,-3..3).
Напишите процедуру с входным параметром а, затем решите дифференциальное уравнение:
с
и
Пусть процедура возвращает f(1) как единственное число (возможно, понадобится применить trace, чтобы всё правильно получить). Затем попробуйте задать разные значения а и посмотрите, можно ли найти хотя бы два значения а (иных, чем 0), для которых f(1)=0. Найдите эти два значения а с точностью до 5 значащих цифр.
Вообще-то это сложная задача. Несколько подсказок не помешают. Не удастся применить внутри процедуры dsolve(...type=numeric), чтобы возвратить число, так как выходом численной версии dsolve является набор уравнений вроде таких:
- restart;
- f:=dsolve({diff(y(t),t$2)=-y(t),y(0)=2,D(y)(0)=0},{y(t)},type=numeric);
- g:=f(1);
С этим уже сталкивались ранее. Тогда для получения присвоенного y(t) числа использовался оператор присваивания:
- assign(g);
Это не сработает, поскольку символ производной не есть правильная переменная для присваивания. Есть два варианта:
(1) заменить ОДУ второго порядка набором связанных ОДУ и применить оператор присваивания для извлечения числа;
(2) узнать как применить команды Maple op или rhs для извлечения числа.
Команда op выдает элементы (величины), которые обычно генерирует Maple: выражения, функции, листы, наборы и т. п. Вернитесь на команду restart, выполните restart, dsolve и g:=f(1);, но не исполняйте оператор assign. Тогда в написанном ниже операторе замените 1 на 2. Посмотрите, что возвратится в результате:
- op(1,g[2]);
Иной способ:
- rhs(g[2]);
Чтобы процедура могла вернуть число, внутри нее надо использовать один из этих методов.
Этот пример несколько техничен, но может пригодиться.
Надо решить сложное уравнение с варьируемым параметром k:
cos(x) = kx,
где k изменяется от 0 до 20. Нужно написать функцию F(k), которая возвращает решение x этого уравнения при любом задаваемом значении k, и затем построить график F(k).
Единственный способ решения – написать процедуру. После исполнения ее команд (ниже) в F присваивается последний вычисленный ею результат, т. е. значение x из fsolve. Реализуйте процедуру, а затем постройте график.
- restart;
Объявление F процедурой:
- F:=proc(k)
Объявление локальных внутренних переменных процедуры:
- locals,x;
Использование fsolve для решения уравнения со значением k, полученным из заголовка процедуры proc(k):
- s:=fsolve(cos(x)-k*x,x,0..2);
Возврат:
- end;
Посмотрим, что получится, если запустить F:
- F(1);F(2);
Строится график в операторном представлении, так как форма plot(F(k),k=0..20) не сработает:
- plot(F,0..20);