Элементы программирования


Настоящее пособие посвящено работе с Maple в интерактивном режиме. Поэтому мы не будем здесь рассматривать внутренний язык программирования Maple в полном объеме. В частности, не будут затронуты вопросы написания и отладки процедур, объявления статуса переменных, создания библиотек и т.д. Мы рассмотрим лишь организацию основных алгоритмических структур: ветвлений и циклов. Используя эти конструкции в блоке команд Maple, объединенных в рабочую группу, мы, с одной стороны, продолжаем работать в интерактивном режиме, а с другой - фактически создаем простейшие программы.
Составной оператор условного перехода имеет структуру:
if < cond > then < block > elif < cond > then < block >... else < block > fi ;
Здесь cond - выражение булевского типа, а block - любая группа команд Maple.

Конструкция elif < cond > then < block > может повторяться несколько раз или вовсе отсутствовать. Часть else < block > тоже не является обязательной.
Часто вместо составного оператора ветвления бывает удобнее использовать функцию ветвления - `if `. Она имеет три аргумента, первый из которых является условием, а второй и третий - возвращаемыми значениями. Если первый аргумент принимает значение true, то возвращаемым значением функции является второй аргумент, а если false - третий. Приведем пример использования функции `if ` :

 

> f:=`if`(x>1,sqrt(x),x^2);plot(f,x=-2..4);

f := `if`(1-x < 0,sqrt(x),x^2)

[Maple Plot]


В Maple существует несколько разновидностей циклов. Стандартный арифметический цикл имеет следующую структуру:
for < var > from < exp1 > by < exp2 > to < exp3 > do < block > od;
Здесь группа команд block выполняется для каждого значения переменной цикла var, которая меняется от значения exp1 до значения exp3 с шагом exp2. Если конструкция from < exp1 > и/или by < exp2 > отсутствует, то соответствующие им выражения принимаются равными 1. Отметим, что переменная цикла может изменять свое значение не только при переходе к следующему шагу цикла, но и внутри тела цикла. Проиллюстрируем это на примере:

 

> for i from 1 by 1 to 10 do i:=i+3 od;

i := 4
i
:= 8
i
:= 12

 

Итерационный цикл имеет структуру:
while < cond > do < block > od ;
Возможен и "гибрид" арифметического и итерационного циклов. Соответствующая конструкция имеет вид:
for < var > from < exp1 > by < exp2 > while < cond > do < block > od ;

Рассмотренные варианты организации циклов характерны (с теми или иными изменениями) для большинства языков программирования. Кроме них, в Maple имеется еще один специфический вид цикла. Как уже упоминалось, выражения в Maple имеют структуру дерева. Перебрать все ветви (операнды) первого уровня можно с помощью специального цикла, имеющего такой синтаксис:
for < var > in < exp > do < block > od ;
Проиллюстрируем работу этого цикла на примерах:

 

> f:=(x^3+3*x+1)*(x^2-x-3)*(x+2); for g in f do g od;

f := (x3 + 3 x + 1) (x2 - x - 3) (x + 2)
x
3 + 3 x + 1
x
2 - x - 3
x
+ 2

> for g in expand(f) do g od;

x6
x
5
-2 x4
-2 x3
-14 x2
-23 x
-6

> s:=0:for i in numtheory[divisors](60) do if numtheory[mobius](i)=1 then s:=s+i fi od;s;

32

 В последнем примере мы нашли сумму тех делителей числа 60, значение функции Мёбиуса от которых, равно 1.

В качестве иллюстрации использования циклов и условных операторов решим такую задачу: найти все пары простых чисел близнецов (так называют простые числа, отличающиеся друг от друга на 2) на отрезке натурального ряда чисел от 8000 до 9000.

 

> printlevel:=0:
>
p:=nextprime(8000):
>
while p<8998 do
>
p1:=p+2:
>
if isprime(p1) then print(p,p1) fi;
>
p:=nextprime(p1)
>
od;

8009, 8011
8087, 8089
8219, 8221
8231, 8233
8291, 8293
8387, 8389
8429, 8431
8537, 8539
8597, 8599
8627, 8629
8819, 8821
8837, 8839
8861, 8863
8969, 8971


Обратите внимание на то, что перед началом вычислений мы присвоили значение 0 зарезервированной переменной printlevel. Дело в том, что на команды, вызываемые из вложенных структур, не распространяется правило регулирования вывода результатов выполнения команды на экран с помощью помещения точки с запятой или двоеточия после соответствующей команды. В этом случае отображаются результаты выполнения всех команд, глубина вложенности которых не превышает текущего значения зарезервированной переменной printlevel. Это делается для того, чтобы программа не печатала слишком много промежуточных результатов. Если же мы все же хотим вывести на экран результаты, получаемые на глубине вложенности, превышающей значение printlevel, достаточно использовать оператор print. По умолчанию значение printlevel равно 1. (Именно этим объясняется, что в примере, где мы вычисляли сумму части делителей числа 60, не были отображены на экране результаты присваиваний s := s+i)


Волгоградский государственный педагогический университет
Кафедра алгебры, геометрии и информатики