Смекни!
smekni.com

Программирование и разработка приложений в Maple (стр. 35 из 135)

В задачу структурного кодирования входит получение корректной программы (модуля) на основе простых управляющих структур. В качестве таких базовых выбираются управляющие структуры следования, ветвления, организации циклов и вызовов функций (процедур, программ); при этом, все перечисленные структуры допускают только один вход и один выход. Более того, первые из трех указанных управляющих структур (следования, ветвления и организации циклов) составляют тот минимальный базис, на основе которого можно создавать любой сложности корректную программу с одним входом, одним выходом, без зацикливаний и недостижимых команд. Детальное обсуждение базисов управляющих структур программирования можно найти, в частности, в книгах [1-3] и в другой доступной литературе по основам программирования.

Следование отражает сам принцип последовательного выполнения предложений программы, пока не встретится изменяющее эту последовательность предложение. Например: Avz:=19.4; Ag:=47.52; Sv:=39*Av-6*Ag; Tal:=Art+Kr; - типичная управляющая структура следования, состоящая из последовательности четырех весьма простых Maple-предложений присваивания.

Ветвление определяет выбор одного из возможных путей дальнейших вычислений; типичными предложениями, обеспечивающими данную управляющую структуру, являются предложения типа «IF A THEN B ELSE C». Структура «цикл» реализует повторное выполнение группы предложений, пока выполняется некоторое логическое условие; типичными предложениями, обеспечивающими данную управляющую структуру, являются предложения: DO, DO_WHILE и DO_UNTIL. Таким образом, базисные структуры определяют соответственно последовательную (следование), условную (ветвление) и итеративную (цикл) передачи управления в программах. При этом, корректная структурированная программа теоретически любой сложности может быть написана с использованием только управляющих структур следования, IF-операторов ветвления и WHILEциклов. Однако расширение набора указанных средств, в первую очередь, за счет обеспечения вызовов функций и механизма процедур существенно облегчает программирование, не нарушая при этом структурированности программ и повышая уровень их модульности. При этом, сочетания (итерации, вложения) корректных структурированных программ, полученные на основе указанных управляющих структур, не нарушают их структурированности и корректности. Любых сложности и размера программы можно получать на основе соответствующего сочетания расширенного базиса (следование, ветвление, цикл, вызовы функций и механизм процедур) управляющих структур. Такой подход позволяет отказаться в программах от использования меток и безусловных переходов. Структура подобных программ четко прослеживается от начала (сверху) и до конца (вниз) при отсутствии передач управления на верхние уровни. Именно в свете сказанного Maple-язык представляет собой достаточно хороший пример лингвистического обеспечения при разработке эффективных структурированных программ, сочетающего лучшие традиции структурно-модульной технологии с ориентацией на математическую область приложений и массу программистски непрофессиональных пользователей из различных прикладных областей, включая и не совсем математической направленности. Для дальнейшего изложения напомним, что под «предложением» в Maple-языке понимается конструкция следующего простого вида:

<Maple-выражение> {;|:}

где в качестве выражения допускается любая корректная с точки зрения языка конструкция, например: A:= sqrt(60 + x): evalb(42 <> 64); sin(x) + x; `Tallinn-2006`:= 6; # Вызов и др. В рассмотренных ниже иллюстративных фрагментах приведено достаточно много различных примеров относительно несложных предложений в рамках управляющей структуры следования, которая достаточно прозрачна и особых пояснений не требует. Предложения кодируются друг за другом, каждое в отдельной строке или в одной строке несколько; завершаются в общем случае {;|:}-разделителями и выполняются строго последовательно, если управляющие структуры ветвления и цикла не определяют другого порядка. В дальнейшем предложения языка будем называть в соответствии с их определяющим назначением, например предложение присваивания, вызова функции, комментария, while-предложение, restart-предложение, if-предложение и т.д. Сделаем лишь одно замечание к предложению присваивания.

Наиболее употребительно определение предложения присваивания посредством одноименного (:=)-оператора, допускающего множественные присвоения. Однако, в целом ряде случаев вычислительные конструкции не допускают его использования. И в этом случае можно успешно использовать следующую процедуру Maple-языка: assign(Id{,|=} <Выражение>)

возвращающую NULL-значение (т.е. ничего) и присваивающую Id-идентификатору вычисленное выражение (которое, начиная с Maple 7, можеть быть и NULL). При этом, процедура assign в качестве единственного фактического аргумента допускает и список/множество уравнений вида Id = <Выражение>, определяющих соответствующие множественные присваивания. Например, списочная структура следующего фрагмента допустима лишь с использованием вышеупомянутой assign-процедуры пакета:

> [x:= 64, y:= 59*x, z:=evalf(sqrt(x^2 + y^2)), x + y + z]; Error, `:=` unexpected

> [assign(x= 64), assign(y, 59*x), assign(z, evalf(sqrt(x^2 + y^2))), x+y+z]; ⇒ [7616.542334] > [assign(x= 42), assign(y, 47*x), assign(z, evalf(sqrt(x^2 + y^2))), x + y + z]; Error, (in assign) invalid arguments

> [assign(['x'= 42, 'y'= 47*x, 'z'= evalf(sqrt(x^2 + y^2))]), x + y + z]; ⇒ [6250.639936]

Первый пример фрагмента иллюстрирует недопустимость использования (:=)-оператора, а три последующих - реализацию этой же списочной структуры на основе процедуры assign. При этом последний пример фрагмента демонстрирует использование невычисленных идентификаторов, обеспечивающих корректность вычислений. Тогда как 3-й пример иллюстрирует ошибочность повторного применения assign для переопределения вычисленных переменных. В дальнейшем assign-процедура широко используется в иллюстративных примерах, а в книге [103] представлен ряд полезных ее расширений.

2.2. Управляющие структуры ветвления Mapleязыка (if-предложение)

Достаточно сложные алгоритмы вычислений, обработки информации и/или управляющие (в первую очередь) не могут обойтись сугубо последовательной схемой, а включают различные конструкции, изменяющие последовательный порядок выполнения алгоритма в зависимости от наступления тех или иных условий: циклы, ветвления, условные и безусловные переходы (такие конструкции иногда называются управляющими). Для организации управляющих конструкций ветвящегося типа Maple-язык располагает довольно эффективным средством, обеспечиваемым if-предложением и имеющим следующие четыре формата кодирования:

(1) if <ЛУ> then <ПП> end if {;|:}

(2) if <ЛУ> then <ПП1> else <ПП2> end if {;|:}

(3) if <ЛУ1> then <ПП1> elif <ЛУ2> then <ПП2> else <ПП3> end if {;|:}

(4) `if`(<ЛУ>, V1, V2)

В качестве логического условия (ЛУ) всех четырех форматов if-предложения выступает любое допустимое булевское выражение, образованное на основе операторов отношения {<|<=|>| >=|=|<>}, логических операторов {and, or,not} и логических констант {true, false, FAIL}, и возвращающее логическое {true|false}-значение. Последовательность предложений (ПП) представляет собой управляющую структуру типа следования, предложения которой завершаются {;|:}-разделителем; для последнего предложения ПП кодирование разделителя необязательно. Во всех форматах, кроме последнего, ключевая фраза `end if` определяет закрывающую скобку (конец) if-предложения и его отсутствие идентифицирует синтаксическую ошибку, вид которой определяется контекстом if-предложения. Каждому if-слову должна строго соответствовать своя закрывающая скобка `end if`.

Первый формат if-предложения несет следующую смысловую нагрузку: если результат вычисления ЛУ возвращает true-значение, то выполняется указанная за ключевым thenсловом ПП, в противном случае выполняется следующее за if предложение, т.е. if-предложение эквивалентно пустому предложению. При этом, если if-предложение завершается (;)-разделителем, то выводятся результаты вычисления всех предложений, образующих ПП, независимо от типа завершающего их {:|;}-разделителя. Следовательно, во избежание вывода и возврата излишней промежуточной информации, завершать if-предложение рекомендуется (:)-разделителем.

Второй формат if-предложения несет следующую смысловую нагрузку: если результат вычисления ЛУ возвращает true-значение, то выполняется указанная за ключевым thenсловом ПП1, в противном случае выполняется следующая за ключевым else-словом ПП2. Замечание относительно вывода промежуточных результатов для случая первого формата if-предложения сохраняет силу и для второго формата кодирования.

ПП1, если evalb(ЛУ1) ⇒ true

ПП2, если (evalb(ЛУ1) ⇒ false)and(evalb(ЛУ2) ⇒ true)

R =ПП==========3, если (==========evalb(ЛУ1) ==========⇒ false)and==========(evalb(ЛУ2) ==========⇒ false)and==========(evalb(ЛУ3)======= ⇒ true)

ППn - 1, если (∀k |k ≤ n- 2)(evalb(ЛУk) ⇒ false)and(evalb(ЛУn - 1) ⇒ true)

ППn, in other cases

Третий формат if-предложения несет смысловую нагрузку, легко усматриваемую из общей R-функции, поясняющей принцип выбора выполняемой ППк в зависимости от цепочки истинности предшествующих ей ЛУj (j = 1 .. k) в предложении (см. выше).

А именно: if-предложение третьего формата возвращает R-результат выполнения ППк тогда и только тогда, когда справедливо следующее определяющее соотношение:

(∀j|j ≤ k-1) (evalb(ЛУj) ⇒ false) and (evalb(ЛУk) ⇒ true)

Данный формат if-предложения является наиболее общим и допускает любой уровень вложенности. Ключевое elif-слово является сокращением от “else if”, что позволяет не увеличивать число закрывающих скобок `end if` в случае вложенности if-предложения.

Наконец, по четвертому формату if-предложения возвращается результат вычисления V1-выражения, если evalb(<ЛУ>) ⇒ true, и V2-выражения в противном случае. Данный формат if-предложения подобно вызову Maple-функции можно использовать в любой конструкции, подобно обычному Maple-выражению, либо отдельным предложением. Следующий фрагмент иллюстрирует применение четырех форматов if-предложения: