Оператор присваивания
Оператор присваивания записывается в виде: переменная = выражение
В зависимости от типов переменной и выражения различают: числовое присваивание, символьное присваивание, логическое присваивание. Любое присваивание, в отличие от других языков программирования может быть векторным, матричным, конформным. Конформность относится как к операндам выражения, так и к переменной и к выражению между собой. Скаляр конформен массиву любого ранга.
Выполнение оператора состоит в вычислении выражения справа от «=» и присвоения результата переменной слева от «=». После выполнения присваивания прежнее значение переменной утрачивается. В отличие от математических формул знак «=» трактуется не как тождество, а как присваивание. Поскольку выражение вычисляется раньше, чем выполняется присваивание, одно и то же имя может быть указано в операторе одновременно слева и справа от знака «=». Например, k=k+1 означает, что текущее значение переменной k увеличивает на 1. К моменту выполнения оператора переменные, входящие в выражение, должны быть определены.
Тип числового выражения назначается автоматически и если он не совпадет с типом переменной, то выполняется преобразование значения вычисленного выражения к типу переменной.
3.4. Ветвления If и циклы Do
Ветвления – конструкции If
Под блоком в Фортране понимают один или несколько выполняемых операторов внутри составного оператора. Передача управления извне внутрь блока запрещена. Конструкции if различаются по числу блоков 0, 1, 2, 3, …. Для реализации многоблочного разветвления имеется расширение elseif (условие) then , а также конструкция, называемая переключателем Select case по целочисленной или символьной переменной.
Таблица 21.
Двухблочный (структурный) условный оператор
Блок-схема | Конструкция If |
If(логическое_выражение) then блок_then между then и else else блок_else между else и endif endif |
Таблица 22.
Одноблочный условный оператор (нет блока_else)
Блок-схема | Конструкция If |
If(логическое_выражение) then блок_then между then и endif endif |
Таблица 23.
Безблочный, по-другому, логический условный оператор
Блок-схема | Конструкция If |
If(логическое_выражение) оператор Пример If(x<0) y=abs(x) По виду блок-схема та же, но в прямоугольнике – единственный простой оператор |
Циклы – конструкции DO
Циклом в программе называют группу (блок) многократно выполняемых операторов. Конструкция do обрамляет цикл
do …
…блок_do…
Enddo
Имеется три разновидности циклов в Фортране:
- бесконечный цикл;
- итеративный цикл (цикл по условию);
- цикл по переменной (с заранее известным числом повторений).
Вспомогательные операторы Exit и Cycle
Во всех трех разновидностях циклов (и только в циклах) можно использовать:
- Exit– досрочный выход из цикла на оператор, непосредственно следующий в тексте за enddo ближайшего охватывающего цикла либо указанного именованного циклаExit имя_цикла;
- Cycle– переход на enddo ближайшего охватывающего цикла либоуказанного именованного циклаCycle имя_цикла .
Таблица 24.
Бесконечный цикл
Блок-схема | Конструкция Do |
do блок_do, в том числе if (на_выход)exit enddo ! только повтор do |
Чтобы выполнение цикла когда-либо закончилось, среди операторов блока_DO бесконечного цикла должен быть хотя бы один exit с условием выхода из цикла.
Таблица 25.
Цикл по условию (итеративный цикл)
Блок-схема | Конструкция Do |
Пока условие выполняется, цикл продолжается Do while(условие) блок_do enddo ! только повтор do |
Цикл по переменной
Переменная в операторе Do– предпочтительнее целая, но также допускается вещественная или вещественная двойной точности. Формула расчета числа повторений цикла .
Начало xn, конец xk и шаг step – константы, переменные или выражения одного из перечисленных типов. Функцияint( ) вычисляет целую часть указанного частного, отбрасывая дробную, без округления. Результат max :
max (0, +) => +max (0, –)=> 0 max (0, 0)=> 0 .
Таблица 26. Цикл по переменной. Опуская подробности, цикл рисуют так
Блок-схема | Конструкция Do |
do переменная = xn, xk, step блок_do enddo |
Цикл не выполнится ни разу, то есть kp=0, если
или
Шаг цикла step регламентируется следующим образом:
- step≠0;
- эквивалентны Do i= 1,10,1 и Do i = 1,10 – по умолчанию step=1;
- если step>0, x возрастает, по окончании цикла x > xk;
- если step<0, x убывает, по окончании цикла x < xk.
Переменная цикла x изменяется по закону арифметической прогрессии. Для понимания того, как это происходит, покажем подробную блок-схему, в которой проясняются все детали и правила для цикла по переменной.
Таблица 27.
Цикл по переменной. Подробная блок-схема цикла.
Подробная блок-схема цикла по переменной | |
Блок-схема | Пояснения |
Здесь х – переменная цикла; xn, xk, step – константы, переменные или выражения. 1) do x=xn,xk,step 2) блок_do 3) enddo 4) конец цикла -продолжение программы enddo – это пункт (3), включающий в себя три действия: - изменение переменной x, - уменьшение k на 1, - переход к (1). |
В соответствии с подробной блок-схемой цикла по переменной выполнение цикла регламентируется следующими правилами:
- переменная x в цикле do изменяется автоматически по закону арифметической прогрессии – изменять ее в блоке_do запрещено;
- не разрешается входить внутрь блока_do извне, поскольку в этом случае не определеночисло повторений цикла kp и переменная x;
- переменные xn, xk, step можно изменять в цикле – это не повлияет на число повторений уже запущенного цикла;
- оператор cycle, встретившийся в блоке_do, прерывает пункт (2) и вызывает переход к end do – пункту (3);
- оператор Exit, встретившийся в блоке_do, прерывает цикл, завершает его досрочно и вызывает переход к пункту (4) – на оператор непосредственно следующий в тексте за end do;
- при нормальном завершении цикла переменная x достигает значения x = xn + step *kp, а при досрочном выходе сохраняется достигнутое значение x из [xn,xk].
Цикл по вещественной переменной x имеет неустойчивый характер:
- при некоторых xn, xk, step цикл выполняется для значения x = xk;
- при других xn, xk, step цикл пропускает последнее значение x = xk.
Причина: ошибка в вычислении kp и накопление погрешности округления в x=x+step, особенно при сравнительно малом step по отношению к x.
Такой цикл можно скорректировать, возможны три варианта:
- переделать радикально – построить цикл по целой переменнойinta, через которую выразить вещественную переменную x. Количество повторений kp при этом следует рассчитать самостоятельно перед циклом; int будет изменяться точно, x не станет накапливать погрешность, хотя разовая погрешность сохранится
integer inta,kp; real x
kp = . . .! количество повторений цикла
do int = 0, kp-1 ! kp – число повторений цикла
x = xn + inta * step
! содержимое прежнего блока_do
Enddo
- «подправить» цикл по вещественной переменной, «обманув» do и переписав его так: do x = xn, xk + step/2, step
- выбрать шаг в виде числа, которое является степенью двойки и точно представляется в памяти компьютера, например, 4, 8, 0.25
Среди операторов блока_do может встретиться другая конструкция do. В этом случае говорят о вложенном цикле. Оценивая количество повторений оператора write внутри вложенного цикла в примере, показанном ниже, необходимо помнить, что при каждом повторении внешнего цикла, внутренний цикл повторяется заново.
Пример вложенных конструкций do
DO y = -1., 1., 0.125 ! 17 раз
do x = -1., 1., 0.125 ! 17 раз
WRITE(1,*) x,y ! 289=17*17 раз
Enddo
ENDDO
В файл будет выведена 289 пар значений х и y.
3.5. Параллельные конструкции where и forall
Условия во вновь появившихся конструкциях Фортрана-95 стали векторными, матричными (в общем случае многомерными). Появилась возможность их варьировать покомпонентно. Прежние управляющие конструкции Do While,If иSelect case, ориентированные на скаляры, для этих целей не подошли. Условия в управляющих конструкцияхдолжны быть конформны проводимым вычислениям, см. раздел 5. Новые управляющие конструкции как раз реализуют параллельныедействия над компонентами векторов и матриц (вообще, массивов) под управлением компонент конформной им маски, заданной логическим выражением. Имеется лишь две конструкции: where иforall(появилась в Fortran-95).
Оператор и конструкция where
Ветвлениеwhereпо формезаписываетсяаналогичноif в трёх разновидностях с количеством блоков два, один, ноль
Таблица 28.
Сравнение операторов if и where
Оператор if | Оператор where |
if (скаляр-условие) then !2 блока...!блок ДА else if ....!блок НЕТ end if | where (конформное_условие ) !Два блока ....!блок ДА - _действия, конформные условию else where .... !блок НЕТ - действия, конформные условию end where |
if (скаляр-условие) then !1 блок ...!блок ДА end if | where (конформное_условие ) !Один блок ....!блок ДА - действия, конформные условию end where |
if (скаляр-условие) !один простой ! без блоков | where(конформное_условие ) !один конформный !без блоков |
Отметим внешнее сходство if и where–оба ветвления. Однако между ними есть кардинальные отличия:
- if задает скалярное ветвление, группируя действия над скалярами или векторами целиком;
- where– это векторное покомпонентное ветвление, котороегруппирует параллельные действия над компонентами векторов, матриц, многомерных массивов, секций с непременным требованием конформности условия и действий.
Имеется также определенное сходство whereс do – оба могут обрабатывать массивы. Правда, do может задавать закон изменения лишь одного индекса массива по какому-либо измерению, а whereобеспечивает работу по всем компонентам массива независимо, не важно, сколько в нем измерений. Следует подчеркнуть, что имеется принципиальное различиеdo иwhere:
- Do обрабатывает компоненты вектора последовательно;
- where обрабатывает компоненты вектора независимо, параллельно.
Так что where - это вовсе не цикл, а перечисление потенциально параллельных процессов. Реально параллельность достигается только в случае распараллеливающего компилятора и наличия многих процессоров. В случае, когда компилятор не умеет распараллеливать,конструкцияwhere для одномерного массива как бы заменяет do и if.
Порядок действий, соответствующих where:
- вычисляется конформная маска;
- затем над всеми элементами конформных массивов выполняются конформные действия - одно или несколько в последовательности заданной в блоке where;
- действия выполняются только для истинных значений в маске;
- действия выполняются параллельно.
Как всегда, параллельность – это прежде всего независимость процессов, потенциальная способность – в том смысле, что это станет реальностью:
- если будет использован распараллеливающий компилятор IFC;
- если процессоров будет предостаточно;
- если процессоров будет недостаточно, то поочередно пачками, как решит компилятор и операционная система;
- ввиду многих задач и многих пользователей ситуация по числу свободных процессоров может меняться, что затрудняет наши измерения времени решения задачи;
- если компилятор не распараллеливает или процессор единственный, то действия выполняются поочередно по всем элементам, правда, программа выглядит короче.
Пример: найти сумму обратных величин матрицы. Приведем три варианта решения.
1. Рассмотрим сначала на первый взгляд простое решение, которое можно охарактеризовать как “ловушку для начинающих”
RealSumObr
Real,dimension(1:10,1:10) :: A
SumObr=Sum( 1/A, A/=0 )
Ошибка состоит в непонимании порядка действий
- сначала вычисляем аргумент 1/A и рискуем ”поделить на 0” для нулевой компоненты вектора A;
- потом суммируем по маске A/=0.
2. Вычисление обратной величины Obr логично выполнить в виде двухблочной конструкции where
RealSumObr
Real,dimension (1:10,1:10):: A, Obr
where (A/=0 ) !сдвумя блоками
Obr=1/A ! где можно – вычислить обратную величину
else where
Obr=0 ! где нельзя – обнулить обратную величину
end where
SumObr=Sum(Obr)
3. Вычисление обратной величины можно выполнить и в виде простого оператора where
Real SumObr
real,dimension(1:10,1:10) :: A,Obr
Obr=0;
where (A/=0) Obr=1/A ! безблочный оператор
SumObr=Sum(Obr)
Дата добавления: 2016-02-13; просмотров: 906;