Смекни!
smekni.com

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

> if (64 <> 59) then V:= 42: G:= 47: S:= evalf(sqrt(G - V), 6) end if: S; ⇒ 2.23607

> x:= 57: if type(x,'prime') then y:=x^2-99: z:=evalf(sqrt(y)) else NULL end if; y+z; ⇒ y + z > if (64 = 59) then V:= 42 else G:= 47: S:=evalf(sqrt(57 - G), 6) end if: [V, S]; ⇒ [42, 3.16228] > if (64 = 59) then V:= 42 elif (64 <= 59) then G:= 47 elif (39 >= 59) then S:= 67 elif (9 = 2) then Art:= 17 else `ArtVGS` end if; ⇒ ArtVGS

> AGN:= `if`(64 <> 59, 59, 64): Ar:= sqrt(621 + `if`(10 < 17, 2, z)^2): [AGN, Ar]; ⇒ [59, 25]

> if (64 = 59) then H:= `if`(3 <> 52, 52, 57) elif (57 <= 52) then H:= `if`(57 <> 52, 52, 57) elif

(32 >= 52) then S:= 67 elif (10 = 3) then Art:= 17 else `ArtVGS` end if; ⇒ ArtVGS

> V:= 64: G:= 59: if (V <> G) then S:= 39; if (V = 64) then Art:= 17; if (G = 59) then R:= G + V end if end if end if; ⇒ S := 39 > [%, S, Art, R]; ⇒ [123, 39, 17, 123]

> F:=x -> `if`(x < 39, S(x), `if`((39<=x) and (x<59), G(x), `if`((59<=x) and (x<64), V(x), Z(x)))): > [F(25), F(50), F(55), F(60), F(95), F(99)]; ⇒ [39, 59, 59, 64, Z(95), Z(99)]

Последний пример фрагмента иллюстрирует использование четвертого формата if-предложения для определения кусочно-определенной функции. Описание допустимых конструкций в качестве ЛУ и ПП для if-предложения обсуждалось выше, там же приведен целый ряд примеров по его применению. Ниже будет дана его дальнейшая детализация в контексте различного назначения иллюстративных фрагментов Maple-языка.

Синтаксис Maple-языка допускает также if-предложения следующего формата:

if <ЛУ1> then if < ЛУ2> then ... if <ЛУn> then <ПП> end if end if ... end if {;|:}

ЛУk - логические условия и ПП - последовательность предложений. Данного формата ifконструкция выполняется корректно, но результат возвращается без вывода. Его можно использовать по {%|%%|%%%}-предложению или по переменной, которой он был присвоен зараннее, как это иллюстрирует следующий простой фрагмент:

> V:=64: G:=59: if (V<>G) then if (V=64) then if (G=59) then R:= G+V end if end if end if;

> [%, R]; ⇒ [123, 123]

> if (V<>G) then S:=39; if (V=64) then Art:= 17; if (G=59) then R:=G+V end if end if end if;

S := 39

> [%, S, Art, R]; ⇒ [123, 39, 17, 123]

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

> [[a, b], `if`(eval(a) <> eval(b), true, false)]; ⇒ [[a, b], true]

> `if`(FAIL = FAIL, true, false); ⇒ true

С другой стороны, как иллюстрирует последний пример фрагмента, if-предложение отождествляет FAIL-значения, сводя различные неопределенности к единой, что также не соответствует здравому смыслу. Однако, причина этого лежит не в самом if-предложении, а в трактовке языком неопределенности, которая обсуждалась нами детально в [12].

Предложение if представляет собой наиболее типичное средство обеспечения ветвящихся алгоритмов. В этом контексте следует отметить, что аналогичное предложение Mathязыка пакета Mathematica [6,7] представляется нам существенно более выразительным, позволяя проще описывать ветвящиеся алгоритмы [33,39,41,42].

Наконец, Maple-язык допускает использование и безусловных переходов на основе встроенной функции goto, кодируемой в виде goto(<Метка>). Данная функция по вполне понятным причинам, обусловленным структурным подходом к программированию, недокументирована. Однако, в целом ряде случаев использование данного средства весьма эффективно, например, при необходимости погрузить в Maple-среду программу, использующую безусловные переходы на основе goto-предложения. Типичным примером являются Fortran-программы, широко распространенные в научных приложениях. Из нашего опыта следует отметить, что использование функции goto существенно упростило погружение в Maple целого комплекса физико-технических Fortran-программ, использующих goto-конструкции. Между тем, goto-функция имеет смысл только в теле процедуры, обеспечивая в точке вызова goto(<Метка>) переход к Maple-предложению, перед которым установлена указанная Метка. При этом, в качестве метки выступает некоторый идентификатор, как это иллюстрирует следующий простой фрагмент:

> A:= proc(x) `if`(x > 64, goto(L1), `if`(x < 59, goto(L2), goto(Fin)));

L1: return x^2;

L2: return 10*x + 17;

Fin: NULL end proc:

> A(350), A(39), A(64), A(10), A(17), A(64), A(59); ⇒ 122500, 407, 117, 187

При использовании вызовов goto(<Метка>) следует иметь в виду, что Метка является глобальной переменной, что предполагает ее выбор таким образом, чтобы она не пересекалась с переменными текущего сеанса, находящимися вне тела процедуры, использующей goto-переходы. Нами была определена процедура isplabel [41,103], использующая простой подход защиты goto-меток, который состоит в следующем. Если процедура использует, например, метки L1, L2, ..., Ln, то в начале исходного текста процедуры кодируется вызов unassign('L1', 'L2', ..., 'Ln'). Это позволяет обеспечивать ошибкоустойчивость всех меток процедуры. Однако данный подход требует определенной уверенности, что отмена значения L-метки не будет отрицательно сказываться на выполнении документа текущего сеанса, если он использует одноименную переменную L вне тела процедуры. Процедура uglobal [103] позволяет в Maple-процедуре работать с глобальными переменными, не заботясь о возможности нежелательных последствий такого решения на глобальном уровне текущего сеанса пакета. Детальнее вопросы использования goto-функции Maple-языка и средства, сопутствующие ее использованию, рассматриваются в рамках нашей Библиотеки [103]. Рассмотрев средства организации ветвления вычислительного алгоритма, переходим к средствам организации циклических конструкций в среде языка пакета Maple.

2.3. Циклические управляющие структуры Mapleязыка (while_do-предложение)

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

(1.a) for <ПЦ> in <Выражение> while <ЛУ> do <ПП> end do {;|:}

(1.b) for <ПЦ> in <Выражение> do <ПП> end do {;|:}

(1.c) in <Выражение> while <ЛУ> do <ПП> end do {;|:}

(1.d) in <Выражение> do <ПП> end do {;|:}

(1.e) do <ПП> end do {;|:}

(2.a) for <ПЦ> from <A> by <B> to <C> while <ЛУ> do <ПП> end do {;|:}

(2.b) for <ПЦ> from <A> to <C> while <ЛУ> do <ПП> end do {;|:}

(2.c) for <ПЦ> from <A> while <ЛУ> do <ПП> end do {;|:}

(2.d) for <ПЦ> while <ЛУ> do <ПП> end do {;|:}

(2.e) while <ЛУ> do <ПП> end do {;|:}

Наиболее общего вида вариант (1.а) первого формата while_do-предложения несет следующую смысловую нагрузку: для заданной переменной цикла (ПЦ), принимающей в качестве значений значения последовательных операндов указанного после in-слова выражения, циклически повторяется вычисление последовательности предложений (ПП), ограниченной скобками {do ….. end do}, до тех пор, пока логическое условие (ЛУ) возвращает true-значение (см. прилож. 3 [12]). В качестве выражения, как правило, выступают список, множество и диапазон, тогда как относительно ЛУ имеет место силу все сказанное для случая if-предложения. При этом, значения операндов, составляющих выражение, могут носить как числовой, так и символьный характер. Сказанное в адрес if-предложения относится и к типу используемого для предложения while_do завершающего его {;|:}-разделителя.

После завершения while_do-предложения управление получает следующее за ним предложение. Смысл вариантов (1.b..1.d) первого формата while_do-предложения с учетом сказанного достаточно прозрачен и особых пояснений не требует. Следующий простой фрагмент иллюстрирует принципы выполнения всех вариантов первого формата предложения while_do по организации циклических вычислений:

Первый формат while_do-предложения

> x:= 1: for k in {10, 17, 39, 44, 59, 64} while (x <=4 ) do printf(`%s%a, %s%a, %s%a|`, `k=`, k, `k^2=`, k^2, `k^3=`, k^3); x:= x + 1 end do:

k=10, k^2=100, k^3=1000|k=17, k^2=289, k^3=4913|k=39, k^2=1521, k^3=59319|k=44, k^2=1936, k^3=85184|

> for k in (h$h=1 .. 13) do printf(`%a|`, k^2) end do:

1|4|9|16|25|36|49|64|81|100|121|144|169|

> k:= 0: in (h$h=1 .. 99) while (not type(k, 'prime')) do k:=k+1: printf(`%a|`, k^2) end do:

1|4|

> do V:= 64: G:= 59: S:= 39: Ar:= 17: Kr:= 10: Arn:= 44: R:= V + G + S + Ar + Kr + Arn:

printf(`%s%a`, `R=`, R); break end do: R=233 > M:= {}: N:= {}: for k in [3, 10, 32, 37, 52, 57] do if type(k/4, 'odd') then break end if; M:= `union`(M, {k}); end do: M; # (1) ⇒ {3, 10, 32, 37}

> for k in [3, 10, 32, 37, 52, 57] do if type(k/2, 'odd') then next end if; N:= `union`(N, {k}); end do: N; # (2) ⇒ {3, 32, 37, 52, 57}

> T:= time(): K:=0: t:=10: do K:=K+1: z:= time() - T: if (z >= t) then break else next end if

end do: printf(`%s %a %s`, `Обработка =`, round(K/z), `оп/сек`); # (3) Обработка = 313587 оп/сек

> AG:=array(1..4,1..4): for k in a$a=1..4 do for j in a$a=1..4 do AG[k,j]:= k^j+j^k end do end do: AV:=copy(AG): for k in a$a=1..4 do for j in a$a=1..4 do if (k=j) then AG[k, j]:=0 else AG[k, j]:= k^j + j^k end if end do end do: print(AV, AG);

2534 321783 14517544 145512325, 0435 173203 1451704 1453205



> restart; N:= {}: for h in [F(x), G(x), H(x), S(x), Art(x), Kr(x)] do N:= `union`(N, {R(h)}) end do: N; # (4) ⇒ {R(F(x)), R(G(x)), R(H(x)), R(S(x)), R(Art(x)), R(Kr(x))}

> map(R, {F(x), G(x), H(x), S(x), Art(x)}); ⇒ {R(F(x)), R(G(x)), R(H(x)), R(S(x)), R(Art(x))} > restart: for h in [F, G, H, S] do map(h, [x, y, z, t, u]) end do;

[F(x), F(y), F(z), F(t), F(u)]

[G(x), G(y), G(z), G(t), G(u)]

[H(x), H(y), H(z), H(t), H(u)]

[S(x), S(y), S(z), S(t), S(u)]

Второй формат while_do-предложения

> S:= {}: for k from 1 by 2 to infinity while (k <= 25) do S:= `union`(S, {k^3}) end do: S;

{1, 27, 125, 343, 729, 1331, 2197, 3375, 4913, 6859, 9261, 12167, 15625}

> S:= []: for k from 1 to infinity while (k <= 18) do S:= [op(S), k^3] end do: S;

[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000, 1331, 1728, 2197, 2744, 3375, 4096, 4913, 5832]

> S:= []: for k while (k <= 18) do S:= [op(S), k^3] end do: S;

[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000, 1331, 1728, 2197, 2744, 3375, 4096, 4913, 5832] > S:= []: p:= 0: while (p <= 10) do p:= p + 1: S:= [op(S), p^3] end do: S;

[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000, 1331]

> S:= [ ]: p:= 0: do p:= p + 1: if (p > 15) then break end if; S:= [op(S), p^3] end do: S;

[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000, 1331, 1728, 2197, 2744, 3375]

> h:= 0: for k from 19.42 by 0.001 to 20.06 do h:= h + k: end do: h; ⇒ 12653.340 > print("Прошу подготовить CD-ROM с АРМ - Вы располагаете одной мин.!"); T:= time(): do if time() - T >= 10 then break end if end do: print("Продолжение вычислений после ожидания:"); # (5)

"Прошу подготовить CD-ROM с АРМ - Вы располагаете одной мин.!"

"Продолжение вычислений после ожидания:"

Несколько пояснений следует сделать относительно варианта (1.e) первого формата, который в общем случае определяет бесконечный цикл, если среди ПП не определено программного выхода из него или не производится внешнего прерывания по stop-кнопке 3й строки GUI. В общем же случае для обеспечения выхода из циклической конструкции служит управляющее break-слово, в результате вычисления которого производится немедленный выход из содержащей его конструкции с передачей управления следующему за ней предложению. В случае вложенных циклов передача управления производится циклу, внешнему относительно break-содержащего цикла.