Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
современный фортран , Бортеньев.pdf
Скачиваний:
242
Добавлен:
26.03.2015
Размер:
2.34 Mб
Скачать

О. В. Бартеньев. Современный ФОРТРАН

пренебрежение такой ошибкой приводит к созданию неработоспособных программ, например следующий цикл является бесконечным, поскольку x из-за ошибки округления не принимает значения, точно равного 1.0.

Пример:

real :: x = 0.1

 

do

! Бесконечный цикл

print *, x

 

x = x + 0.1

 

if(x == 1.0) exit

! EXIT - оператор выхода из цикла

end do

 

Нормальное завершение цикла можно обеспечить так:

real :: x = 0.1

 

do

 

print *, x

 

x = x + 0.1

! x практически равен 1.0

if(abs(x - 1.0) < 1.0e-5) exit

end do

! ABS(x - 1.0) возвращает |x - 1.0|

Общий вывод из приведенного примера: нельзя сравнивать вещественные числа на предмет точного равенства или неравенства, а следует выполнять их сравнение с некоторой точностью.

Влияние ошибок округления можно снизить, правильно формируя порядок вычислений. Пусть, например, объявлены и инициализированы переменные x, y и z:

real(4) :: x = 1.0e+30, y = -1.0e+30, z = 5.0

Их сумма равна 5.0. Однако найдем и выведем их сумму так:

print *, x + (y + z)

!

0.000000E+00 (ошибка)

Результат ошибочен. Правильной является такая последовательность вычислений:

print *, (x + y) + z

!

5.000000

(верно)

5.2. Выражения отношения и логические выражения

Выражение отношения сравнивает значения двух арифметических или символьных выражений. Арифметическое выражение можно сравнить с символьным выражением. При этом арифметическое выражение рассматривается как символьное - последовательность байтов. Результатом выражения отношения является .TRUE. или .FALSE..

Операндами выражения отношения могут быть как скаляры, так и массивы или их сечения, например:

(/ 1, 2, 3 /) > (/ 0, 3, 0 /)

! Возвращает массив (T F T)

Операции отношения могут быть записаны в двух формах:

.LT. или < меньше;

162

5. Выражения, операции и присваивание

.LE. или <=

меньше или равно;

.GT. или >

больше;

.GE. или >=

больше или равно;

.EQ. или ==

равно;

.NE. или /=

не равно.

Пробелы в записи обозначения операции являются ошибкой:

a . le. b

! Ошибка. Правильно: a .le. b

a < = b

! Ошибка. Правильно: a <= b

Все операции отношения являются двуместными (бинарными) и должны появляться между операндами. Выполняются операции отношения слева направо.

Если в выражении отношения один операнд имеет вещественный, а другой целый тип, то перед выполнением операции целочисленный операнд преобразовывается в вещественный тип.

Выражения отношения с символьными операндами сравниваются посимвольно. Фактически выполняется сравнение кодов символов сравниваемых строк. При сравнении строк разной длины короткая строка увеличивается до длины большей строки за счет добавления завершающих пробелов, например выражение 'Expression' > 'Exp1' вычисляется как 'Ex-

pression' > 'Exp1

' (здесь символ

обозначает пробел).

Операнды выражения отношения

могут иметь и комплексный тип.

В этом случае можно применять только операции .NE. (/=) и .EQ. (==). Логические выражения имеют результатом логическое значение истина -

.TRUE. илиложь - .FALSE.. Операндами логических выражений могут быть:

логические константы, переменные и функции;

массивы логического и целого типа и их сечения;

выражения отношения;

целочисленные константы, переменные и функции.

Логические операции:

.NOT. логическое НЕ (отрицание);

.AND. логическое И;

.OR. логическое ИЛИ;

.XOR. логическое исключающее ИЛИ;

.EQV. эквивалентность;

.NEQV. неэквивалентность.

Все логические операции, кроме отрицания, являются бинарными. Логическая операция .NOT. является унарной и располагается перед операндом. Выполняются логические операции слева направо.

163

О. В. Бартеньев. Современный ФОРТРАН

В табл. 5.1 приведены результаты логических операций над логическими переменными x и y, принимающими значения истина (И) и ложь (Л).

Таблица 5.1. Таблица истинности

x

y

x .AND. y

x .OR. y

.NOT. x

x .XOR. y

x .EQV. y

x .NEQV. y

 

 

 

 

 

 

 

 

И

И

И

И

Л

Л

И

Л

И

Л

Л

И

Л

И

Л

И

Л

И

Л

И

И

И

Л

И

Л

Л

Л

Л

И

Л

И

Л

 

 

 

 

 

 

 

 

Операнды логических операций должны быть логического типа. Однако CVF и FPS также допускают использование операндов целого типа. В этом случае логические операции выполняются побитово. Если операнды имеют различные разновидности целого типа, то выполняется преобразование типов - операнд целого типа меньшего ранга преобразовывается в целый тип наибольшего ранга. Логическое выражение с целочисленными операндами имеет результат целого, а не логического типа, например:

write(*, *) 2#1000 .or. 2#0001

!

9

( = 1001 )

write(*, *) 8 .or. 1

!

9

 

Часто логические выражения с целочисленными операндами применяются для маскирования тех или иных разрядов.

Пример маскирования старшего байта:

integer(2) :: mask = #00ff

! Маска mask и число k заданы в

integer(2) :: k = #5577

! шестнадцатеричной системе счисления

write(*, '(z)') mask .and. k

! 77 (в шестнадцатеричной системе счисления)

Операции отношения и логические операции выполняются слева направо, т. е., если две последовательные операции имеют равный приоритет, первоначально выполняется левая операция.

Пример. Вычислить результат логического выражения

x / a == 1 .or. b / (a + b) < 1 .and. .not. b == a .or. x /= 6

при x = 6.0, a = 2.0 и b = 3.0.

Вычислив результат арифметических операций и операций отношения, получим:

.false. .or. .true. .and. .not. .false. .or. .false.

Далее выполняем пошагово логические операции с учетом их приоритета. После выполнения .not. .false.:

.false. .or. .true. .and. .true. .or. .false.

После выполнения .true. .and. .true.:

.false. .or. .true. .or. .false.

164

5. Выражения, операции и присваивание

Окончательный результат: .TRUE.

Пример. Записать условие попадания точки в область, которая является пересечением эллипса и треугольника, образованного графиками функций y = |x| и y = 2 (рис. 5.1).

y

1

x

2

Рис. 5.1. Исследуемая область

if(x**2/4 + y**2 < 1.0 .and. y > abs(x)) then write(*, *) 'Inside'

else

write(*, *) 'Outside' end if

Логической переменной можно присвоить значение целочисленного выражения, которое интерпретируется как истина, если отлично от нуля, и как ложь, если равно нулю. С другой стороны, логические величины можно использовать в арифметических выражениях. В этом случае .TRUE. интерпретируется как единица, а .FALSE. - как нуль. И как следствие этого свойства, результат логического выражения можно присвоить числовой переменной. Однако если логическая переменная, например g1, получила свое значения, например 11, в результате вычисления целочисленного выражения, то при последующем использовании g1 в арифметическом выражении ее значение будет равно 11, а не единице. Например:

integer :: k = 22, m = 0

 

 

 

 

logical g1, g2

 

 

 

 

g1 = k / 2; g2 = m * k

 

 

 

 

print *, g1, g2

!

T F

 

 

print *, 3*g1, 3*(.not.g2), 3**g2

!

33

-3

1

k = .not. g1 .or. .not. g2

 

 

 

 

print *, k

!

-1

 

 

Замечание. Свойства CVF и FPS, позволяющие смешивать логические и целочисленные данные, являются расширением по отношению к стандарту Фортран 90.

5.3. Задаваемые операции

Действие встроенных операций (одноместных и двуместных) может быть распространено на производные типы данных, для которых не определено ни одной встроенной операции. Механизм расширения области действия операции называется перегрузкой операции. Помимо этого могут быть заданы и дополнительные операции.

Механизм перегрузки и задания двуместной операции x op y:

165

О. В. Бартеньев. Современный ФОРТРАН

составить функцию fop с двумя обязательными параметрами x и y, имеющими вид связи IN, которая будет вызываться для реализации задаваемой операции op с операндами x и y и будет возвращать результат операции;

при помощи оператора INTERFACE OPERATOR(op) связать функцию fop с операцией op.

Тогда результатом операции x op y будет возвращаемое функцией fop(x, y) значение, т. е. следующие операторы эквивалентны:

z = x op y

z = fop(x, y)

Аналогично реализуется механизм задания и перегрузки одноместной операции (разд. 8.12.2).

Пример. Задать операцию вычисления процента x от y.

interface operator(.c.)

 

! Связываем операцию .c.

real(4) function percent(x, y)

 

! с функцией percent

real(4), intent(in) :: x, y

 

 

end function percent

 

 

end interface

 

 

print '(1x,f5.1)', 5.0 .c. 10.0

 

! 50.0

print '(1x,f5.1)', percent(5.0, 10.0)

! 50.0

end

 

 

real(4) function percent(x, y)

! Эта функция вызывается при

real(4), intent(in) :: x, y

! выполнении операции .c.

percent = x / y * 100.0

 

 

end function percent

 

 

Замечание. Реализующая операцию функция может быть модульной процедурой (разд. 8.12.2).

Задаваемая операция должна всегда обрамляться точками. Типы операндов задаваемой операции должны строго соответствовать типам параметров вызываемой при выполнении операции функции. Так, в нашем примере попытка выполнить операцию 5 .c. 10 приведет к ошибке, поскольку типы операндов отличны от REAL(4).

При перегрузке операций отношения, для обозначения которых существует две формы, перегрузка распространяется на обе формы операции. Например, если перегружена операция >=, то таким же образом будет перегружена и операция .GE..

Более подробно механизмы задания и перегрузки операций изложены в разд. 8.12.

166