Программирование: логика, циклы, процедуры

Как написать свою программу в Maple, используя логику, циклы и процедуры

Версия для печати

Процедуры: подключение к работе
циклов и логики

Возможно, уже понятно, что циклы и логика – мутное дело. Они занимают много места на рабочем листе, и повторная работа с ними требует дополнительных действий, например, курсором. Эти действия можно автоматизировать, поместив их в нечто, что работает как функция, а вам останется только задавать ей значения и получать ответ. Такая структура вызывается командой 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);
Задача 8.6

Исправим процедуру cosdeg так, чтобы она возвращала число с плавающей запятой. Удостоверьтесь, что исправления есть только внутри процедуры, а не в вызове ее из программы.

Если посмотрите на новую процедуру cosdeg, увидите, что она применяется в точности как функция. Но поскольку это самостоятельная программа, она может быть достаточно сложной. Именно поэтому пишутся собственные процедуры. Следует внимательно следить, чтобы определенная таким способом функция не пересекалась с именами команд Maple. Кроме того, следует помнить, что собственные процедуры работают медленнее, чем «родные» команды Maple.

Задача 8.7 о вычислении кубического β-сплайна

Напишите процедуру, вычисляющую кубический β-сплайн. Выше говорилось, что piecewise работает лучше, чем команды if, но здесь if будет работать отлично, поскольку все помещается внутрь собственной процедуры. Для доказательства не используйте в этой задаче piecewise. Нарисуйте график в интервале –3..3. Заметьте, что возвращаемый ответ должен быть последним результатом процедуры, чтобы его можно было нарисовать. Внутрь процедуры передаются только независимые переменные. То есть для одномерной функции следует использовать B:=proc(x), для двумерной – C:=proc(x,y) и т. д. При рисовании результат процедуры рассматривается как функция и применяется команда plot(f(x),x=a..b) или используется оператор Maple, в котором нет упоминания х: plot(B,-3..3).

Задача 8.8

Напишите процедуру с входным параметром а, затем решите дифференциальное уравнение:

с и

Пусть процедура возвращает 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]);

Чтобы процедура могла вернуть число, внутри нее надо использовать один из этих методов.

Пример. Рисование результатов fsolve

Этот пример несколько техничен, но может пригодиться.

Надо решить сложное уравнение с варьируемым параметром 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);