Цель лекции: познакомиться с основами реализации процедурного стиля программирования в языке программирования Mathematica
В предыдущих лекциях мы познакомились с двумя наиболее естественным для Mathematica стилями программирования — функциональным и стилем, основанным на правилах преобразований. Однако Mathematica позволяет также программировать, используя исторически первый и традиционный стиль для большинства языков программирования (Фортран, Паскаль, С и др.) — процедурный стиль. Процедурный стиль в отличие от остальных зачастую не самым эффективным образом использует машинные ресурсы, но он более нагляден, более привычен для пользователей и именно поэтому он поддерживается Mathematica и успешно используется при решении многих задач.
В данной лекции мы рассмотрим процедурный стиль программирования, за основу взяв книги Е. М. Воробьёва [1], П. Веллина и др. [14] и С. Мангано [11].
Условные функции позволяют задавать различный характер вычислений в зависимости от выполнения или невыполнения одного или нескольких условий. В языках программирования их принято называть условными операторами. Будем придерживаться этой традиции и мы. Более строго условный оператор или оператор ветвления определяется следующим образом: это конструкция языка программирования, обеспечивающая выполнение определённой команды (набора команд) только при условии истинности некоторого логического выражения, либо выполнение одной из нескольких команд (наборов команд) в зависимости от значения некоторого выражения.
Наиболее простым в использовании является оператор If. Как правило, он задаётся в виде If[cond,expr1,expr2]. Результат вычисления данного выражения есть выражение expr1, если при вычислении cond возвращается True, и, соответственно, выражение expr2, если вычисление cond даёт False.
Для иллюстрации действия оператора If и других условных операторов рассмотрим следующую задачу. Пусть на плоскости задана некоторая точка, которая в полярных координатах описывается произвольным отличным от нуля радиусом r и углом a. Зная величину угла a, нам необходимо определить, какой (верхней или нижней относительно оси абсцисс) полуплоскости принадлежит эта точка. Саму ось абсцисс мы отнесём к верхней полуплоскости. Для наглядности см. рис. 11.1.
(рис 11.1) Графическое пояснение к примерам на рисунках 11.2 – 11.4
В In[1] на рис. 11.2 мы задали пользовательскую функцию pos одного аргумента a, тело которой содержит условный оператор. При обращении к этой функции с некоторым значением аргумента a в выходной ячейке печатается фраза "точка лежит в нижней полуплоскости", если синус значения аргумента a принимает отрицательные значения, и "точка лежит в верхней полуплоскости", если положительные или 0; в примерах In[2] и In[3] мы проверяем действие нашего условного оператора для значений аргумента, удовлетворяющих каждому из условий.
Если вычисление выражения cond не возвращает ни True, ни False, условный оператор остаётся невычисленным и перепечатывается в ячейку Out в исходном виде. В качестве иллюстрации в примере In[4] на рис. 11.2 мы задали в качестве аргумента нашей функции pos выражение, отличное от числа.
Для того чтобы любой результат вычисления выражения cond приводил к вычислению условного оператора, используется расширенная форма условного оператора, которая выглядит как If[cond,expr1,expr2,expr3]. В этом случае, если вычисление выражения cond не возвращает ни True, ни False, результатом вычисления условного оператора будет являться выражение expr3.
В In[5] на рис. 11.2 мы задали новую пользовательскую функцию pos2 одного аргумента a. При обращении к этой функции с некоторым значением аргумента x в выходной ячейке печатается фраза "точка лежит в левой полуплоскости", если косинус значения аргумента a принимает отрицательные значения, и "точка лежит в правой полуплоскости", если положительные или 0. Если ни первое, ни второе условие не выполняется (когда значение аргумента a не является числом), печатается фраза "значение аргумента должно быть численным". В примерах In[6], In[7] и In[8] мы обращаемся к нашей функции при значениях аргументов, инициирующих разные результаты вычисления оператора If.
(рис 11.2) Задание алгоритма действий при помощи условного оператора If
В качестве аргументов expr1,expr2 и expr3 оператора If могут выступать абсолютно любые выражение Mathematica, в том числе и другие условные операторы. Таким образом, помимо задания дихотомии, выбора между двух взаимоисключающих условий, используя определённое сочетание условных операторов, можно задавать любое количество исключающих друг друга условий, выполнение которых влечёт различные результаты вычислений.
В следующем примере мы ещё более конкретизируем положение нашей точки на координатной плоскости. Мы определим её положение с точностью до квадранта и отдельно установим, если точка лежит на оси координат.
В In[1] на рис. 11.3 мы задали пользовательскую функцию posByIf от одного аргумента a. При обращении к этой функции с некоторым значением аргумента a в случае, если синус a принимает отрицательные значения, то выполняется вложенный условный оператор. Этот оператор проверяет, является ли косинус аргумента отрицательным. В случае если это так, печатается фраза "точка принадлежит квадранту III". В противном случае выполняется ещё один условный оператор, который проверяет, не принимает ли выражение Cos[a] нулевых значений: в случае, если принимает, печатается фраза "точка лежит на оси ординат", в противном случае печатается фраза "точка принадлежит квадранту IV". Если синус аргумента a не принимает отрицательных значений, выполняется иная последовательность, в которой определяется принадлежность значения аргумента a первому или второму квадрантам, либо осям абсцисс или ординат. В примере In[2] мы проверяем действие нашей функции posByIf для нескольких значений аргумента.
Подробней о функции If см. книги Е. М. Воробьёва [1, с. 167–168] и П. Веллина и др. [14, с. 131–135].
(рис 11.3) Задание вложенных условных операторов
Хотя выражение в In[1] на рис. 11.3 работает эффективно и правильно (в чём мы убедились в In[2]), сама запись условий при помощи каскада условных операторов достаточно громоздка и крайне неудобна для восприятия.
Задать выполнение тех же самых действий при тех же самых условиях можно гораздо более простым способом — воспользовавшись оператором множественных альтернатив Which. Как уточняет Е. М. Воробьёв [1, с. 169], "условный оператор Which[test1,expr1,test2,expr2,...] имеет четное число 2n аргументов, среди которых n тестов testi и п выражений expri". При вычислении выражения Which[...] конечным результатом является результат вычисления первого из expri, для которого соответствующее условие testi возвращает True.
Зададим при помощи оператора Which новую пользовательскую функцию posByWhich, которая осуществляет те же действия, что и заданная при помощи If функция posByIf — см. In[1] на рис. 11.4. Результаты действия обеих функций (Out[2] на рисунках 11.3 и 11.4) полностью идентичны.
(рис 11.4) Задание алгоритма действий при помощи условного оператора Which
Если все выражения test1 возвращают при вычислении False, значение выражения с заголовком Which равняется Null. Порой оказывается полезным в этом случае заставить Mathematica выполнять какое-либо действие, например, выводить сообщение. Для этих целей Е. М. Воробьёв [1, с. 169] предлагает в качестве последних двух аргументов функции Which добавить ещё одну пару test,expr, при этом вместо test следует указать выражение True, а вместо expr — требуемое действие.
В примере In[1] на рис. 11.5 мы задали условный оператор Which, задав в нём заведомо неверные условия. При попытке его вычислить мы даже не удостоились вывода на экран ячейки Out. В примере In[2] на том же рисунке к аргументам выражения Which[...] мы добавили ещё два — True и "какая-то ошибка". Теперь, заставив Mathematica вычислить вновь заданное выражение, мы всё-таки получили от программы ответ.
Если в процессе вычисления выражения Which[...] первые тесты вернули значение False, и дошла очередь до теста, которые имеет отличное от булевого значение, то редуцированное выражение Which[...] просто перепечатывается в ячейку Out (см. пример In[3] на рис. 11.5).
Подробней о функции Which см. книги Е. М. Воробьёва [1, с. 169] и П. Веллина и др. [14, с. 136–137].
(рис 11.5) Реакция оператора Which на нестандартные ситуации
Осуществлять ветвление вычислений, то есть, для одного и того же выражения возвращать при вычислении разные результаты, можно не только в зависимости от выполнения некоторых логических условий, но и в зависимости от вида самого выражения. Функция Switch[expr,patt1,expr1,patt2,expr2,...] вычисляет выражение expr1, если expr соответствует шаблону patt1, вычисляет expr2, если expr соответствует шаблону patt2 и т.д. Если выражение expr соответствует сразу нескольким шаблонам, вычисляется то выражение expri, подходящий шаблон которого patti проверяется раньше остальных.
В примере In[1] на рис. 11.6 мы определяем пользовательскую функцию powercheck одного аргумента, которая выясняет, является ли её аргумент символом в степени 1, 2, 3 или 4, и печатает соответствующее сообщение: первая степень, квадрат, куб, четвёртая степень. В примере In[2] мы проверяем действие нашей функции powercheck на нескольких примерах.
В предыдущем примере мы задали в качестве аргументов функции powercheck только такие выражения, которые соответствуют одному из шаблонов в её теле. В примере In[3] на рис 11.6 мы опробовали действие powercheck на выражении, шаблона для которого в её теле нет. В Out[3] в качестве результата мы получили переписанное в исходном виде входящее в тело функции powercheck выражение Switch[...].
Для того, чтобы функция Switch определённым образом реагировала на ситуацию, когда выражению expr не находится подходящего шаблона, например, выполняла выражение exprlast, то в качестве последних двух аргументов функции Switch добавляют выражение _,exprlast. В примере In[4] на рис 11.6 мы немного модифицируем нашу функцию powercheck, добавив в Switch пару новых аргументов. Теперь на отличное от символа в степени 1, 2, 3 или 4 выражение, введённое в качестве аргумента, функция powercheck будет выдавать сообщение "введите другое выражение".
Подробней о функции Switch см. книги Е. М. Воробьёва [1, с. 170–171] и П. Веллина и др. [14, с. 136–137].
(рис 11.6) Использование функции Switch для ветвления вычислений
Использование условных операторов оказывается непременным при задании кусочных математических функций. Специально для этих целей в Mathematica имеется функция Piecewise. В простейшем случае она задаётся как Piecewise[{{expr1,cond1},{expr2,cond2},...}]. При вычислении данной функции вычисляется выражение expr1, если выполняется условие cond1, вычисляется выражение expr2, если выполняется условие cond2 и т.д. Если ни одно из условий не выполняется, то результатом вычисления Piecewise является 0; для того, чтобы задать вместо 0 другое выражение otherexpr, следует указать его в качестве последнего аргумента функции Piecewise.
В примере In[1] на рис. 11.7 мы задаём математическую функцию одного аргумента x, которая возвращает -x, когда x<-1 и x2, когда x>1; в остальных случаях функция принимает значение 1. В In[2] мы строим график нашей зависимости от аргумента x.
П. Веллин и др. в книге [14, с. 138] при помощи Piecewise определяет функцию, возвращающую абсолютное значение аргумента. В In[3] на рис. 11.7 определим функцию abswal, имеющую то же назначение. В примерах In[4] и In[5] мы проверяем действие функции abswal на числе -5 и символе h. В последнем примере ячейка Out[5] содержит результат вычисления функции abswal[h] отдельно для отрицательного и положительного значений h. Результатом дифференцирования abswal[h] также является набор значений в зависимости от знака аргумента h — см. примере In[6].
Подробней о функции Piecewise см. книгу П. Веллина и др. [14, с. 138–139].
(рис 11.7) Задание кусочных функций при помощи Piecewise
Для описания оператора Do воспользуемся подходом Е. М. Воробьёва [1, с. 164–167].
Одним из основных операторов процедурного (равно как функционального и основанного на правилах преобразований) программирования является оператор присваивания Set. Преимуществом Mathematica перед другими языками программирования является то, что нет необходимости заранее определять тип выражения, которому осуществляется присваивание. Одному и тому же символу можно присвоить как символьные, так и численные значения, как комплексные, так и действительные величины.
Если в пределах одной ячейки мы несколько раз подряд осуществим операцию присваивания, разделяя следующие друг за другом выражения знаком " ; ", то записанные выражения в совокупности также будут являть собой некоторое выражение, которое называется составным выражением и имеет заголовок CompoundExpression.
В примере In[1] на рис. 11.8 при помощи функции FullForm мы вывели на экран внутреннюю форму некоторого составного выражения a=b;b=c;c=d;d=5, при этом мы воспользовались функцией Hold для того, чтобы функция FullForm применялась непосредственно к заданному выражению, а не к результату его вычисления. Как мы видим в Out[1], дано выражение действительно имеет заголовок CompoundExpression.
Е. М. Воробьёв в [1, с. 165] отмечает следующее: "Оператором, в известном смысле имитирующим CompoundExpression, является оператор Do". По большому счёту, оператор Do организует цикл. Цикл — это разновидность управляющей конструкции в языках программирования высокого уровня, предназначенная для организации многократного исполнения набора инструкций.
Выражение Do[expr,{imax}], заданное в простейшей форме, imax раз вычисляет выражение expr. Очевидно, что это выражение полностью эквивалентно выражению expr;expr;...;expr;, при этом стоит отметить, что последнее выражение в данном составном выражении также завершается знаком " ; ". Таким образом, после вычисления выражения Do[expr,{imax}] ячейка Out не генерируется.
В примерах In[2] и In[4] на рис. 11.8 мы пять раз вычислили выражение $$x=2*x+3$$, задав перед вычислением значение $$x=4$$: в In[2] мы воспользовались оператором Do, а в In[4] записали составное выражение; в In[3] и In[5] мы вывели на экран результаты соответствующих вычислений. Результаты в Out[3] и Out[5], как и ожидалось, совпадают.
(рис 11.8) Многократное вычисление выражения при помощи оператора Do
Второй аргумент функции Do, отвечающий за число и характер повторений, может задаваться точно так же, как и для функции создания списков Table (см. лекцию 3 настоящего курса) и также называется итератором.
Так функция Do[expr,{i,imax}] вычисляет imax выражение expr, при этом expr может содержать символ i, который, в свою очередь, дискретно меняется от 1 до imax с шагом единица. При задании итератора в форме {i,imin,imax} значение символа i с шагом единица меняется от imin до imax. Добавленный в итератор {i,imin,imax,step} четвёртый аргумент step задаёт шаг изменения i. Выражение i может быть любым, но заголовок его не должен быть защищён от присвоения атрибутом Protected. Аргументы итератора imin, imax и step также необязательно должны быть числами, но выражение (imax-imin)/step должно быть числом. В случае, когда imax меньше imin, выражение step может принимать отрицательные значения.
Функция Do является по истине универсальной. На рис. 11.9 продемонстрированы несколько примеров, когда функция Do выполняет роли других встроенных функций Mathematica. В In[1] и In[2] приведён пример, аналогичный примеру в книге Е. М. Воробьёва [1, с. 167], демонстрирующий, что универсальная функция Do порой может заменить функцию суммирования Sum. Здесь же мы впервые задали итератор, содержащий два аргумента: некоторый символ i, входящий в вычисляемое выражение, и количество повторений. Примеры In[3] и In[4] иллюстрируют возможность заменить функцией Do функцию умножения Product. Заданный с тремя аргументами итератор теперь задаёт ещё и нижнюю границу изменения значений символа i. В примере In[5] мы многократно вызываем некоторую неопределённую функцию f, аргументами которой являются результат вычисления этой функции на предыдущем шаге и значение первого аргумента итератора i. При этом i меняется от 2 до 20 с заданным нами интервалом 5.
Подробней о функции Do см. книги Е. М. Воробьёва [1, с. 164–167] и П. Веллина и др. [14, с. 117–120].
(рис 11.9) Использование универсальной Do как альтернативы некоторым встроенным функциям Mathematica
Оператор Do[expr,imax] вычисляет выражение или набор выражений expr заранее заданное пользователем число раз imax. Однако может случиться, что заданного количества вычислений оказывается недостаточно для получения требуемого результата, либо заданное количество вычислений избыточно. В этом случае придётся либо вручную изменить количество повторений в исходном цикле, либо задавать ещё один (а то и несколько) цикл Do, выполняющий недостающее количество вычислений.
Ещё один выход из данной ситуации заключается в использовании встроенной функции While. При задании функции в виде While[cond,expr] вычисление начинается с проверки условия cond. Если проверка возвращает значение True, то вычисляется выражение expr. В процессе вычисления expr условие cond должно быть каким-либо образом изменено. На следующем шаге снова проверяется (уже изменённое) условие cond: если вновь возвращается True, то вычисляется и выражение expr. Цикл повторяется до тех пор, пока проверка cond не вернёт значения False (Е. М. Воробьёв [1, с. 171]).
Для иллюстрации эффективности использования функции While при решении некоторых задач воспользуемся изящным примером, приведённым в книге П. Веллина и др. [14, с. 117–119], а именно, зададим средствами Mathematica функцию, которая ищет нули заданной математической функции, используя метод Ньютона (также известный как метод касательных). Метод Ньютона есть итерационный численный метод. Поиск решения осуществляется путём построения последовательных приближений. Для нахождения корня какой-либо функции $$f(x)$$ применяется следующий алгоритм:
x_0;На рис. 11.10 мы по аналогии с примером в книге П. Веллина и др. [14, с.120], реализуем метод Ньютона при помощи оператора Do. Пусть нам необходимо найти нули параболы $$-(x+1)^3+10$$. В примере In[1] мы задаём пользовательскую функцию, в теле которой содержатся заданная математическая функция, а аргументом является аргумент математической функции. В In[2] мы для наглядности строим график зависимости нашей математической функции от аргумента x. В In[3] мы последовательно задаём начальное приближение, x0=10, задаём цикл Do, который вычисляет итерационную формулу 5 раз, и выводим полученное после всех итераций значение приближения x0. Именно это значение и напечаталось в Out[5]. Количество итераций (а именно, 5) мы задали случайным образом. Достаточно ли точное значение мы получили в результате вычислений? Не превышает ли погрешность (отличие приближения от истинного значения) хотя бы одной тысячной? Для сравнения проведём вычисление итерационной формулы 10 раз при том же начальном приближении — пример In[6]. Результаты вычислений в Out[5] и Out[7] оказываются значительно отличающимися друг от друга.
Таким образом, при реализации метода Ньютона для нахождения нулей функции при помощи оператора Do мы можем задавать только количество итераций, но не допустимую точность нахождения приближения.
(рис 11.10) Реализация метода Ньютона для нахождения нулей функции при помощи функции Do
На рис. 11.11 мы, как и П. Веллин и др. [14, с. 124–125], реализовали тот же алгоритм при помощи оператора While. В примере In[2] мы задали цикл While, который повторяет вычисление итерационной формулы до тех пор, пока полученное приближённое вычисление не будет совпадать с истинным с точностью до одной миллионной. Нам не пришлось наугад задавать количество итераций в надежде добиться требуемой точности, Mathematica сделала это самостоятельно.
Ещё более упростить задание алгоритма Ньютона нам позволит функция NestWhile[func,incond,test], которая на каждой итерации вычисляет выражение func при начальных условиях incond до тех пор, пока выполняется условие test.
Вновь воспользуемся примером из книги П. Веллина и др. [14, с. 127–128]. В In[4] на рис. 11.11 мы определяем пользовательскую функцию NMfindRoot, первый аргумент которой — функция, нули которой требуется найти, второй — начальное приближение, и третий — требуемая точность. В In[5] мы опробуем действие вновь определённой пользовательской функции NMfindRoot на всё том же выражении $$f[x_]:=-(x+1)^3+10$$, задав NMfindRoot[f,10,0.000001].
Откроем маленький секрет: находя нули математической функции при помощи FindRoot, Mathematica пользуется именно методом Ньютона. В примере In[6] на рис. 11.11 мы для сравнения находим ноль нашей функции $$-(x+1)^3+10$$ при помощи FindRoot.
Подробней о функциях While и NestWhile см. книги Е. М. Воробьёва [1, с. 171–172] и П. Веллина и др. [14, с. 123–128].
(рис 11.11) Реализация метода Ньютона для нахождения нулей функции при помощи функций While и NestWhile
Ещё одним условным оператором Mathematica является оператор For. По функционалу он очень похож на оператор While. Заданный в виде For[istart,icond,ichange,expr] он инициирует некоторое начальное выражение istart, а затем многократно вычисляет выражения ichange и expr, пока условие icond возвращает True. Часто istart задаёт начальное значение некоторого счётчика i, icond — условие, которому значение i должно подчиняться, чтобы выражение expr было вычислено, а ichange — выражение, изменяющее значение счётчика i согласно некоторой закономерности.
В In[1] на рис. 11.12 представлен простейший пример использования цикла For. Он выводит на экран при помощи выражения Print[i] значение счётчика i, которое меняется от стартового значения i=1 и должно удовлетворять условию i<5. На каждой итерации значение i увеличивается на единицу при помощи выражения i++. Вместо i++ можно задать i=i+1.
В примере In[3] на рис. 11.12 мы задаём алгоритм, реализующий так полюбившийся нам метод Ньютона. Решение этой задачи при помощи оператора For оказалось не менее простым и изящным, чем при помощи While и NestWhile. В этом примере мы немного изменили (упростили) порядок задания аргументов функции For: мы намеренно пропустили отвечающее за изменение значение счётчика выражение ichange, и включили выполняющее его роль выражение i=f[x0] в expr.
Подробней о функции For см. книгу Е. М. Воробьёва [1, с. 172–173].
(рис 11.12) Задание условных циклов при помощи оператора For
Процессом выполнения циклов, заданных любым из обозначенных выше способов, можно управлять: принудительно их завершать, пропускать итерации, приостанавливать и возобновлять. Именно для целей управления циклами предназначены функции, описанные в данном пункте.
Функция Abort[] принудительно прекращает выполнение цикла и в качестве результата выдаёт сообщение Aborted.
Функция Break[] осуществляет выход из тела цикла, в котором она задана, и возвращает значение Null. Ячейка Out со значением Null при этом не генерируется.
Функция Continue[] инициирует переход к следующей итерации текущего цикла.
Функция Return[] прерывает выполнение цикла и возвращает Null, а заданная с аргументом Return[expr] возвращает значение выражения expr.
В. П. Дьяконов в своей книге [2, с. 127] называет такие функции директивами-функциями.
На рис. 11.13 проиллюстрировано использование перечисленных функций прерывания и продолжения циклов. Мы задали цикл Do, который на каждом шаге печатает номер этого шага. В примере In[1] мы вышли из тела цикла при помощи Break[], как только номер шага превысил число 2: выходная ячейка не была сгенерирована вовсе. В In[2] мы прервали при помощи Abort[] выполнение нашего цикла, как только номер шага превысил число 2: в выходной ячейке возникло сообщение Aborted. В In[3] мы прервали при помощи Return["some message"] выполнение нашего цикла, как только номер шага превысил число 2 и результатом вывели некоторое сообщение some message. В In[4] в процессе выполнения цикла мы перескочили шаги с третьего по восьмой, ничего не выводя на экран, при помощи Continue[].
(рис 11.13) Примеры применения функции прерывания и продолжения циклов
Ещё одна функция прерывания Interrupt[] при обращении к ней в процессе выполнения цикла инициирует вмешательство пользователя: выдаётся диалоговое окно, в котором предлагает осуществить некоторый набор действий, например, продолжить выполнение цикла либо прервать его — см. пример на рис. 11.14.
Подробней о функциях прерывания и продожения циклов см. в книге В. П. Дьяконова [2, с. 127–128].
(рис 11.14) Пример использования функции прерывания Interrupt
В своей совокупности описанные выше операторы циклов и условий позволяют осуществить любое ветвление вычислений. Однако порой оказывается гораздо проще в явном виде указать программе, к какой области кода следует перейти в данный момент. Осуществляется это при помощи оператора безусловного перехода Goto[mark]. Этот оператор всегда действует в связке с другой встроенной функцией Label[mark], которая отмечает место программы, к которому осуществляется переход.
В примере на рис. 11.15 задан простейший цикл, реализованный с помощи оператора безусловного перехода. Он выводит на экран значение некоторого выражения x до тех пор, пока оно не превысит значение 10.
Подробней о задании безусловных переходов см. книгу В. П. Дьяконова [2, с. 131].
(рис 11.15) Задание цикла при помощи оператора безусловного перехода Goto
Составными называются выражения с заголовком CompoundExpression, представляющие собой следующие друг за другом и разделённые знаком " ; " более простые выражения.
Условный оператор (оператор ветвления) — это конструкция языка программирования, обеспечивающая выполнение определённой команды (набора команд) только при условии истинности некоторого логического выражения, либо выполнение одной из нескольких команд (наборов команд) в зависимости от значения некоторого выражения.
Цикл — это разновидность управляющей конструкции в языках программирования высокого уровня, предназначенная для организации многократного исполнения набора инструкций.
В данной лекции мы познакомились с основами процедурного стиля программирования на языке программирования Mathematica. В частности при помощи условных операторов мы научились ветвить процесс вычислений в зависимости от выполнения заданных условий. Мы научились в компактной форме задавать многократно выполняемые однотипные вычисления при помощи циклов, а также инициировать выполнение вычислений в требуемой части программы при помощи безусловных переходов. Мы познакомились с встроенными функциями Mathematica позволяющими управлять процессом выполнения циклов в частности и ходом вычислений в целом. Мы познакомились с правилами хорошего тона при написании программ.
If? Опишите алгоритм его работы.Which? Как он задаётся? Опишите алгоритм его работы.Switch? Как он задаётся? Опишите алгоритм его работы.While? Опишите алгоритм его работы. В чём заключается отличие между операторами While и NestWhile?For? Опишите алгоритм его работы.Abort[], Break[], Continue[], Return[], Interrupt[]?В настоящем задании создайте пользовательскую функцию двух переменных, определяющую, к какому квадранту координатной плоскости принадлежит или на какой координатной оси лежит точка, если заданы её декартовы координаты.
Piecewise.
UnitStep, которая будучи заданной в виде UnitStep[x] возвращает 0 для x<0 и 1 для x\ge0.UnitTriangle, которая будучи заданной в виде UnitTriangle[x] возвращает 1-|x| для |x|<1 и 0 в остальных случаях.UnitBox, которая будучи заданной в виде UnitBox[x] возвращает 1 для |x|<1/2 и 0 в остальных случаях.Sign, которая будучи заданной в виде Sign[x] возвращает -1, 0 или 1, если x принимает отрицательное, нулевое или положительное значения соответственно. typefunc одного аргумента arg со следующим назначением. Если аргумент arg является символом или числом, то typefunc должна возвращать тип arg. Если аргумент arg является списком, то typefunc должна возвращать также список, элементами которого являются типы элементов исходного списка arg.Factorial и двойного факториала Factorial2. В теле пользовательской функции должен содержаться хотя бы один из операторов циклов.n, заполненная n различными символами таким образом, чтобы ни в одной строке и ни в одном столбце не было повторяющихся символов. Выполните следующее задание, которое даёт Е. М. Воробьём в книге [1, с. 176], а именно определите пользовательскую функцию, которая порождала бы случайным образом латинский квадрат заданного порядка.Цель лекции: познакомиться с основами реализации процедурного стиля программирования в языке программирования Mathematica
В предыдущих лекциях мы познакомились с двумя наиболее естественным для Mathematica стилями программирования — функциональным и стилем, основанным на правилах преобразований. Однако Mathematica позволяет также программировать, используя исторически первый и традиционный стиль для большинства языков программирования (Фортран, Паскаль, С и др.) — процедурный стиль. Процедурный стиль в отличие от остальных зачастую не самым эффективным образом использует машинные ресурсы, но он более нагляден, более привычен для пользователей и именно поэтому он поддерживается Mathematica и успешно используется при решении многих задач.
В данной лекции мы рассмотрим процедурный стиль программирования, за основу взяв книги Е. М. Воробьёва [1], П. Веллина и др. [14] и С. Мангано [11].
Условные функции позволяют задавать различный характер вычислений в зависимости от выполнения или невыполнения одного или нескольких условий. В языках программирования их принято называть условными операторами. Будем придерживаться этой традиции и мы. Более строго условный оператор или оператор ветвления определяется следующим образом: это конструкция языка программирования, обеспечивающая выполнение определённой команды (набора команд) только при условии истинности некоторого логического выражения, либо выполнение одной из нескольких команд (наборов команд) в зависимости от значения некоторого выражения.
Наиболее простым в использовании является оператор If. Как правило, он задаётся в виде If[cond,expr1,expr2]. Результат вычисления данного выражения есть выражение expr1, если при вычислении cond возвращается True, и, соответственно, выражение expr2, если вычисление cond даёт False.
Для иллюстрации действия оператора If и других условных операторов рассмотрим следующую задачу. Пусть на плоскости задана некоторая точка, которая в полярных координатах описывается произвольным отличным от нуля радиусом r и углом a. Зная величину угла a, нам необходимо определить, какой (верхней или нижней относительно оси абсцисс) полуплоскости принадлежит эта точка. Саму ось абсцисс мы отнесём к верхней полуплоскости. Для наглядности см. рис. 11.1.
(рис 11.1) Графическое пояснение к примерам на рисунках 11.2 – 11.4
В In[1] на рис. 11.2 мы задали пользовательскую функцию pos одного аргумента a, тело которой содержит условный оператор. При обращении к этой функции с некоторым значением аргумента a в выходной ячейке печатается фраза "точка лежит в нижней полуплоскости", если синус значения аргумента a принимает отрицательные значения, и "точка лежит в верхней полуплоскости", если положительные или 0; в примерах In[2] и In[3] мы проверяем действие нашего условного оператора для значений аргумента, удовлетворяющих каждому из условий.
Если вычисление выражения cond не возвращает ни True, ни False, условный оператор остаётся невычисленным и перепечатывается в ячейку Out в исходном виде. В качестве иллюстрации в примере In[4] на рис. 11.2 мы задали в качестве аргумента нашей функции pos выражение, отличное от числа.
Для того чтобы любой результат вычисления выражения cond приводил к вычислению условного оператора, используется расширенная форма условного оператора, которая выглядит как If[cond,expr1,expr2,expr3]. В этом случае, если вычисление выражения cond не возвращает ни True, ни False, результатом вычисления условного оператора будет являться выражение expr3.
В In[5] на рис. 11.2 мы задали новую пользовательскую функцию pos2 одного аргумента a. При обращении к этой функции с некоторым значением аргумента x в выходной ячейке печатается фраза "точка лежит в левой полуплоскости", если косинус значения аргумента a принимает отрицательные значения, и "точка лежит в правой полуплоскости", если положительные или 0. Если ни первое, ни второе условие не выполняется (когда значение аргумента a не является числом), печатается фраза "значение аргумента должно быть численным". В примерах In[6], In[7] и In[8] мы обращаемся к нашей функции при значениях аргументов, инициирующих разные результаты вычисления оператора If.
(рис 11.2) Задание алгоритма действий при помощи условного оператора If
В качестве аргументов expr1,expr2 и expr3 оператора If могут выступать абсолютно любые выражение Mathematica, в том числе и другие условные операторы. Таким образом, помимо задания дихотомии, выбора между двух взаимоисключающих условий, используя определённое сочетание условных операторов, можно задавать любое количество исключающих друг друга условий, выполнение которых влечёт различные результаты вычислений.
В следующем примере мы ещё более конкретизируем положение нашей точки на координатной плоскости. Мы определим её положение с точностью до квадранта и отдельно установим, если точка лежит на оси координат.
В In[1] на рис. 11.3 мы задали пользовательскую функцию posByIf от одного аргумента a. При обращении к этой функции с некоторым значением аргумента a в случае, если синус a принимает отрицательные значения, то выполняется вложенный условный оператор. Этот оператор проверяет, является ли косинус аргумента отрицательным. В случае если это так, печатается фраза "точка принадлежит квадранту III". В противном случае выполняется ещё один условный оператор, который проверяет, не принимает ли выражение Cos[a] нулевых значений: в случае, если принимает, печатается фраза "точка лежит на оси ординат", в противном случае печатается фраза "точка принадлежит квадранту IV". Если синус аргумента a не принимает отрицательных значений, выполняется иная последовательность, в которой определяется принадлежность значения аргумента a первому или второму квадрантам, либо осям абсцисс или ординат. В примере In[2] мы проверяем действие нашей функции posByIf для нескольких значений аргумента.
Подробней о функции If см. книги Е. М. Воробьёва [1, с. 167–168] и П. Веллина и др. [14, с. 131–135].
(рис 11.3) Задание вложенных условных операторов
Хотя выражение в In[1] на рис. 11.3 работает эффективно и правильно (в чём мы убедились в In[2]), сама запись условий при помощи каскада условных операторов достаточно громоздка и крайне неудобна для восприятия.
Задать выполнение тех же самых действий при тех же самых условиях можно гораздо более простым способом — воспользовавшись оператором множественных альтернатив Which. Как уточняет Е. М. Воробьёв [1, с. 169], "условный оператор Which[test1,expr1,test2,expr2,...] имеет четное число 2n аргументов, среди которых n тестов testi и п выражений expri". При вычислении выражения Which[...] конечным результатом является результат вычисления первого из expri, для которого соответствующее условие testi возвращает True.
Зададим при помощи оператора Which новую пользовательскую функцию posByWhich, которая осуществляет те же действия, что и заданная при помощи If функция posByIf — см. In[1] на рис. 11.4. Результаты действия обеих функций (Out[2] на рисунках 11.3 и 11.4) полностью идентичны.
(рис 11.4) Задание алгоритма действий при помощи условного оператора Which
Если все выражения test1 возвращают при вычислении False, значение выражения с заголовком Which равняется Null. Порой оказывается полезным в этом случае заставить Mathematica выполнять какое-либо действие, например, выводить сообщение. Для этих целей Е. М. Воробьёв [1, с. 169] предлагает в качестве последних двух аргументов функции Which добавить ещё одну пару test,expr, при этом вместо test следует указать выражение True, а вместо expr — требуемое действие.
В примере In[1] на рис. 11.5 мы задали условный оператор Which, задав в нём заведомо неверные условия. При попытке его вычислить мы даже не удостоились вывода на экран ячейки Out. В примере In[2] на том же рисунке к аргументам выражения Which[...] мы добавили ещё два — True и "какая-то ошибка". Теперь, заставив Mathematica вычислить вновь заданное выражение, мы всё-таки получили от программы ответ.
Если в процессе вычисления выражения Which[...] первые тесты вернули значение False, и дошла очередь до теста, которые имеет отличное от булевого значение, то редуцированное выражение Which[...] просто перепечатывается в ячейку Out (см. пример In[3] на рис. 11.5).
Подробней о функции Which см. книги Е. М. Воробьёва [1, с. 169] и П. Веллина и др. [14, с. 136–137].
(рис 11.5) Реакция оператора Which на нестандартные ситуации
Осуществлять ветвление вычислений, то есть, для одного и того же выражения возвращать при вычислении разные результаты, можно не только в зависимости от выполнения некоторых логических условий, но и в зависимости от вида самого выражения. Функция Switch[expr,patt1,expr1,patt2,expr2,...] вычисляет выражение expr1, если expr соответствует шаблону patt1, вычисляет expr2, если expr соответствует шаблону patt2 и т.д. Если выражение expr соответствует сразу нескольким шаблонам, вычисляется то выражение expri, подходящий шаблон которого patti проверяется раньше остальных.
В примере In[1] на рис. 11.6 мы определяем пользовательскую функцию powercheck одного аргумента, которая выясняет, является ли её аргумент символом в степени 1, 2, 3 или 4, и печатает соответствующее сообщение: первая степень, квадрат, куб, четвёртая степень. В примере In[2] мы проверяем действие нашей функции powercheck на нескольких примерах.
В предыдущем примере мы задали в качестве аргументов функции powercheck только такие выражения, которые соответствуют одному из шаблонов в её теле. В примере In[3] на рис 11.6 мы опробовали действие powercheck на выражении, шаблона для которого в её теле нет. В Out[3] в качестве результата мы получили переписанное в исходном виде входящее в тело функции powercheck выражение Switch[...].
Для того, чтобы функция Switch определённым образом реагировала на ситуацию, когда выражению expr не находится подходящего шаблона, например, выполняла выражение exprlast, то в качестве последних двух аргументов функции Switch добавляют выражение _,exprlast. В примере In[4] на рис 11.6 мы немного модифицируем нашу функцию powercheck, добавив в Switch пару новых аргументов. Теперь на отличное от символа в степени 1, 2, 3 или 4 выражение, введённое в качестве аргумента, функция powercheck будет выдавать сообщение "введите другое выражение".
Подробней о функции Switch см. книги Е. М. Воробьёва [1, с. 170–171] и П. Веллина и др. [14, с. 136–137].
(рис 11.6) Использование функции Switch для ветвления вычислений
Использование условных операторов оказывается непременным при задании кусочных математических функций. Специально для этих целей в Mathematica имеется функция Piecewise. В простейшем случае она задаётся как Piecewise[{{expr1,cond1},{expr2,cond2},...}]. При вычислении данной функции вычисляется выражение expr1, если выполняется условие cond1, вычисляется выражение expr2, если выполняется условие cond2 и т.д. Если ни одно из условий не выполняется, то результатом вычисления Piecewise является 0; для того, чтобы задать вместо 0 другое выражение otherexpr, следует указать его в качестве последнего аргумента функции Piecewise.
В примере In[1] на рис. 11.7 мы задаём математическую функцию одного аргумента x, которая возвращает -x, когда x<-1 и x2, когда x>1; в остальных случаях функция принимает значение 1. В In[2] мы строим график нашей зависимости от аргумента x.
П. Веллин и др. в книге [14, с. 138] при помощи Piecewise определяет функцию, возвращающую абсолютное значение аргумента. В In[3] на рис. 11.7 определим функцию abswal, имеющую то же назначение. В примерах In[4] и In[5] мы проверяем действие функции abswal на числе -5 и символе h. В последнем примере ячейка Out[5] содержит результат вычисления функции abswal[h] отдельно для отрицательного и положительного значений h. Результатом дифференцирования abswal[h] также является набор значений в зависимости от знака аргумента h — см. примере In[6].
Подробней о функции Piecewise см. книгу П. Веллина и др. [14, с. 138–139].
(рис 11.7) Задание кусочных функций при помощи Piecewise
Для описания оператора Do воспользуемся подходом Е. М. Воробьёва [1, с. 164–167].
Одним из основных операторов процедурного (равно как функционального и основанного на правилах преобразований) программирования является оператор присваивания Set. Преимуществом Mathematica перед другими языками программирования является то, что нет необходимости заранее определять тип выражения, которому осуществляется присваивание. Одному и тому же символу можно присвоить как символьные, так и численные значения, как комплексные, так и действительные величины.
Если в пределах одной ячейки мы несколько раз подряд осуществим операцию присваивания, разделяя следующие друг за другом выражения знаком " ; ", то записанные выражения в совокупности также будут являть собой некоторое выражение, которое называется составным выражением и имеет заголовок CompoundExpression.
В примере In[1] на рис. 11.8 при помощи функции FullForm мы вывели на экран внутреннюю форму некоторого составного выражения a=b;b=c;c=d;d=5, при этом мы воспользовались функцией Hold для того, чтобы функция FullForm применялась непосредственно к заданному выражению, а не к результату его вычисления. Как мы видим в Out[1], дано выражение действительно имеет заголовок CompoundExpression.
Е. М. Воробьёв в [1, с. 165] отмечает следующее: "Оператором, в известном смысле имитирующим CompoundExpression, является оператор Do". По большому счёту, оператор Do организует цикл. Цикл — это разновидность управляющей конструкции в языках программирования высокого уровня, предназначенная для организации многократного исполнения набора инструкций.
Выражение Do[expr,{imax}], заданное в простейшей форме, imax раз вычисляет выражение expr. Очевидно, что это выражение полностью эквивалентно выражению expr;expr;...;expr;, при этом стоит отметить, что последнее выражение в данном составном выражении также завершается знаком " ; ". Таким образом, после вычисления выражения Do[expr,{imax}] ячейка Out не генерируется.
В примерах In[2] и In[4] на рис. 11.8 мы пять раз вычислили выражение $$x=2*x+3$$, задав перед вычислением значение $$x=4$$: в In[2] мы воспользовались оператором Do, а в In[4] записали составное выражение; в In[3] и In[5] мы вывели на экран результаты соответствующих вычислений. Результаты в Out[3] и Out[5], как и ожидалось, совпадают.
(рис 11.8) Многократное вычисление выражения при помощи оператора Do
Второй аргумент функции Do, отвечающий за число и характер повторений, может задаваться точно так же, как и для функции создания списков Table (см. лекцию 3 настоящего курса) и также называется итератором.
Так функция Do[expr,{i,imax}] вычисляет imax выражение expr, при этом expr может содержать символ i, который, в свою очередь, дискретно меняется от 1 до imax с шагом единица. При задании итератора в форме {i,imin,imax} значение символа i с шагом единица меняется от imin до imax. Добавленный в итератор {i,imin,imax,step} четвёртый аргумент step задаёт шаг изменения i. Выражение i может быть любым, но заголовок его не должен быть защищён от присвоения атрибутом Protected. Аргументы итератора imin, imax и step также необязательно должны быть числами, но выражение (imax-imin)/step должно быть числом. В случае, когда imax меньше imin, выражение step может принимать отрицательные значения.
Функция Do является по истине универсальной. На рис. 11.9 продемонстрированы несколько примеров, когда функция Do выполняет роли других встроенных функций Mathematica. В In[1] и In[2] приведён пример, аналогичный примеру в книге Е. М. Воробьёва [1, с. 167], демонстрирующий, что универсальная функция Do порой может заменить функцию суммирования Sum. Здесь же мы впервые задали итератор, содержащий два аргумента: некоторый символ i, входящий в вычисляемое выражение, и количество повторений. Примеры In[3] и In[4] иллюстрируют возможность заменить функцией Do функцию умножения Product. Заданный с тремя аргументами итератор теперь задаёт ещё и нижнюю границу изменения значений символа i. В примере In[5] мы многократно вызываем некоторую неопределённую функцию f, аргументами которой являются результат вычисления этой функции на предыдущем шаге и значение первого аргумента итератора i. При этом i меняется от 2 до 20 с заданным нами интервалом 5.
Подробней о функции Do см. книги Е. М. Воробьёва [1, с. 164–167] и П. Веллина и др. [14, с. 117–120].
(рис 11.9) Использование универсальной Do как альтернативы некоторым встроенным функциям Mathematica
Оператор Do[expr,imax] вычисляет выражение или набор выражений expr заранее заданное пользователем число раз imax. Однако может случиться, что заданного количества вычислений оказывается недостаточно для получения требуемого результата, либо заданное количество вычислений избыточно. В этом случае придётся либо вручную изменить количество повторений в исходном цикле, либо задавать ещё один (а то и несколько) цикл Do, выполняющий недостающее количество вычислений.
Ещё один выход из данной ситуации заключается в использовании встроенной функции While. При задании функции в виде While[cond,expr] вычисление начинается с проверки условия cond. Если проверка возвращает значение True, то вычисляется выражение expr. В процессе вычисления expr условие cond должно быть каким-либо образом изменено. На следующем шаге снова проверяется (уже изменённое) условие cond: если вновь возвращается True, то вычисляется и выражение expr. Цикл повторяется до тех пор, пока проверка cond не вернёт значения False (Е. М. Воробьёв [1, с. 171]).
Для иллюстрации эффективности использования функции While при решении некоторых задач воспользуемся изящным примером, приведённым в книге П. Веллина и др. [14, с. 117–119], а именно, зададим средствами Mathematica функцию, которая ищет нули заданной математической функции, используя метод Ньютона (также известный как метод касательных). Метод Ньютона есть итерационный численный метод. Поиск решения осуществляется путём построения последовательных приближений. Для нахождения корня какой-либо функции $$f(x)$$ применяется следующий алгоритм:
x_0;На рис. 11.10 мы по аналогии с примером в книге П. Веллина и др. [14, с.120], реализуем метод Ньютона при помощи оператора Do. Пусть нам необходимо найти нули параболы $$-(x+1)^3+10$$. В примере In[1] мы задаём пользовательскую функцию, в теле которой содержатся заданная математическая функция, а аргументом является аргумент математической функции. В In[2] мы для наглядности строим график зависимости нашей математической функции от аргумента x. В In[3] мы последовательно задаём начальное приближение, x0=10, задаём цикл Do, который вычисляет итерационную формулу 5 раз, и выводим полученное после всех итераций значение приближения x0. Именно это значение и напечаталось в Out[5]. Количество итераций (а именно, 5) мы задали случайным образом. Достаточно ли точное значение мы получили в результате вычислений? Не превышает ли погрешность (отличие приближения от истинного значения) хотя бы одной тысячной? Для сравнения проведём вычисление итерационной формулы 10 раз при том же начальном приближении — пример In[6]. Результаты вычислений в Out[5] и Out[7] оказываются значительно отличающимися друг от друга.
Таким образом, при реализации метода Ньютона для нахождения нулей функции при помощи оператора Do мы можем задавать только количество итераций, но не допустимую точность нахождения приближения.
(рис 11.10) Реализация метода Ньютона для нахождения нулей функции при помощи функции Do
На рис. 11.11 мы, как и П. Веллин и др. [14, с. 124–125], реализовали тот же алгоритм при помощи оператора While. В примере In[2] мы задали цикл While, который повторяет вычисление итерационной формулы до тех пор, пока полученное приближённое вычисление не будет совпадать с истинным с точностью до одной миллионной. Нам не пришлось наугад задавать количество итераций в надежде добиться требуемой точности, Mathematica сделала это самостоятельно.
Ещё более упростить задание алгоритма Ньютона нам позволит функция NestWhile[func,incond,test], которая на каждой итерации вычисляет выражение func при начальных условиях incond до тех пор, пока выполняется условие test.
Вновь воспользуемся примером из книги П. Веллина и др. [14, с. 127–128]. В In[4] на рис. 11.11 мы определяем пользовательскую функцию NMfindRoot, первый аргумент которой — функция, нули которой требуется найти, второй — начальное приближение, и третий — требуемая точность. В In[5] мы опробуем действие вновь определённой пользовательской функции NMfindRoot на всё том же выражении $$f[x_]:=-(x+1)^3+10$$, задав NMfindRoot[f,10,0.000001].
Откроем маленький секрет: находя нули математической функции при помощи FindRoot, Mathematica пользуется именно методом Ньютона. В примере In[6] на рис. 11.11 мы для сравнения находим ноль нашей функции $$-(x+1)^3+10$$ при помощи FindRoot.
Подробней о функциях While и NestWhile см. книги Е. М. Воробьёва [1, с. 171–172] и П. Веллина и др. [14, с. 123–128].
(рис 11.11) Реализация метода Ньютона для нахождения нулей функции при помощи функций While и NestWhile
Ещё одним условным оператором Mathematica является оператор For. По функционалу он очень похож на оператор While. Заданный в виде For[istart,icond,ichange,expr] он инициирует некоторое начальное выражение istart, а затем многократно вычисляет выражения ichange и expr, пока условие icond возвращает True. Часто istart задаёт начальное значение некоторого счётчика i, icond — условие, которому значение i должно подчиняться, чтобы выражение expr было вычислено, а ichange — выражение, изменяющее значение счётчика i согласно некоторой закономерности.
В In[1] на рис. 11.12 представлен простейший пример использования цикла For. Он выводит на экран при помощи выражения Print[i] значение счётчика i, которое меняется от стартового значения i=1 и должно удовлетворять условию i<5. На каждой итерации значение i увеличивается на единицу при помощи выражения i++. Вместо i++ можно задать i=i+1.
В примере In[3] на рис. 11.12 мы задаём алгоритм, реализующий так полюбившийся нам метод Ньютона. Решение этой задачи при помощи оператора For оказалось не менее простым и изящным, чем при помощи While и NestWhile. В этом примере мы немного изменили (упростили) порядок задания аргументов функции For: мы намеренно пропустили отвечающее за изменение значение счётчика выражение ichange, и включили выполняющее его роль выражение i=f[x0] в expr.
Подробней о функции For см. книгу Е. М. Воробьёва [1, с. 172–173].
(рис 11.12) Задание условных циклов при помощи оператора For
Процессом выполнения циклов, заданных любым из обозначенных выше способов, можно управлять: принудительно их завершать, пропускать итерации, приостанавливать и возобновлять. Именно для целей управления циклами предназначены функции, описанные в данном пункте.
Функция Abort[] принудительно прекращает выполнение цикла и в качестве результата выдаёт сообщение Aborted.
Функция Break[] осуществляет выход из тела цикла, в котором она задана, и возвращает значение Null. Ячейка Out со значением Null при этом не генерируется.
Функция Continue[] инициирует переход к следующей итерации текущего цикла.
Функция Return[] прерывает выполнение цикла и возвращает Null, а заданная с аргументом Return[expr] возвращает значение выражения expr.
В. П. Дьяконов в своей книге [2, с. 127] называет такие функции директивами-функциями.
На рис. 11.13 проиллюстрировано использование перечисленных функций прерывания и продолжения циклов. Мы задали цикл Do, который на каждом шаге печатает номер этого шага. В примере In[1] мы вышли из тела цикла при помощи Break[], как только номер шага превысил число 2: выходная ячейка не была сгенерирована вовсе. В In[2] мы прервали при помощи Abort[] выполнение нашего цикла, как только номер шага превысил число 2: в выходной ячейке возникло сообщение Aborted. В In[3] мы прервали при помощи Return["some message"] выполнение нашего цикла, как только номер шага превысил число 2 и результатом вывели некоторое сообщение some message. В In[4] в процессе выполнения цикла мы перескочили шаги с третьего по восьмой, ничего не выводя на экран, при помощи Continue[].
(рис 11.13) Примеры применения функции прерывания и продолжения циклов
Ещё одна функция прерывания Interrupt[] при обращении к ней в процессе выполнения цикла инициирует вмешательство пользователя: выдаётся диалоговое окно, в котором предлагает осуществить некоторый набор действий, например, продолжить выполнение цикла либо прервать его — см. пример на рис. 11.14.
Подробней о функциях прерывания и продожения циклов см. в книге В. П. Дьяконова [2, с. 127–128].
(рис 11.14) Пример использования функции прерывания Interrupt
В своей совокупности описанные выше операторы циклов и условий позволяют осуществить любое ветвление вычислений. Однако порой оказывается гораздо проще в явном виде указать программе, к какой области кода следует перейти в данный момент. Осуществляется это при помощи оператора безусловного перехода Goto[mark]. Этот оператор всегда действует в связке с другой встроенной функцией Label[mark], которая отмечает место программы, к которому осуществляется переход.
В примере на рис. 11.15 задан простейший цикл, реализованный с помощи оператора безусловного перехода. Он выводит на экран значение некоторого выражения x до тех пор, пока оно не превысит значение 10.
Подробней о задании безусловных переходов см. книгу В. П. Дьяконова [2, с. 131].
(рис 11.15) Задание цикла при помощи оператора безусловного перехода Goto
Составными называются выражения с заголовком CompoundExpression, представляющие собой следующие друг за другом и разделённые знаком " ; " более простые выражения.
Условный оператор (оператор ветвления) — это конструкция языка программирования, обеспечивающая выполнение определённой команды (набора команд) только при условии истинности некоторого логического выражения, либо выполнение одной из нескольких команд (наборов команд) в зависимости от значения некоторого выражения.
Цикл — это разновидность управляющей конструкции в языках программирования высокого уровня, предназначенная для организации многократного исполнения набора инструкций.
В данной лекции мы познакомились с основами процедурного стиля программирования на языке программирования Mathematica. В частности при помощи условных операторов мы научились ветвить процесс вычислений в зависимости от выполнения заданных условий. Мы научились в компактной форме задавать многократно выполняемые однотипные вычисления при помощи циклов, а также инициировать выполнение вычислений в требуемой части программы при помощи безусловных переходов. Мы познакомились с встроенными функциями Mathematica позволяющими управлять процессом выполнения циклов в частности и ходом вычислений в целом. Мы познакомились с правилами хорошего тона при написании программ.
If? Опишите алгоритм его работы.Which? Как он задаётся? Опишите алгоритм его работы.Switch? Как он задаётся? Опишите алгоритм его работы.While? Опишите алгоритм его работы. В чём заключается отличие между операторами While и NestWhile?For? Опишите алгоритм его работы.Abort[], Break[], Continue[], Return[], Interrupt[]?В настоящем задании создайте пользовательскую функцию двух переменных, определяющую, к какому квадранту координатной плоскости принадлежит или на какой координатной оси лежит точка, если заданы её декартовы координаты.
Piecewise.
UnitStep, которая будучи заданной в виде UnitStep[x] возвращает 0 для x<0 и 1 для x\ge0.UnitTriangle, которая будучи заданной в виде UnitTriangle[x] возвращает 1-|x| для |x|<1 и 0 в остальных случаях.UnitBox, которая будучи заданной в виде UnitBox[x] возвращает 1 для |x|<1/2 и 0 в остальных случаях.Sign, которая будучи заданной в виде Sign[x] возвращает -1, 0 или 1, если x принимает отрицательное, нулевое или положительное значения соответственно. typefunc одного аргумента arg со следующим назначением. Если аргумент arg является символом или числом, то typefunc должна возвращать тип arg. Если аргумент arg является списком, то typefunc должна возвращать также список, элементами которого являются типы элементов исходного списка arg.Factorial и двойного факториала Factorial2. В теле пользовательской функции должен содержаться хотя бы один из операторов циклов.n, заполненная n различными символами таким образом, чтобы ни в одной строке и ни в одном столбце не было повторяющихся символов. Выполните следующее задание, которое даёт Е. М. Воробьём в книге [1, с. 176], а именно определите пользовательскую функцию, которая порождала бы случайным образом латинский квадрат заданного порядка.Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.