Главная страница
Навигация по странице:

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

  • Замечание.

  • 5.6. Описательные выражения

  • 5.7. Присваивание

  • современный фортран , Бортеньев. О. В. Бартеньев Современный Фортран


    Скачать 2.24 Mb.
    НазваниеО. В. Бартеньев Современный Фортран
    Анкорсовременный фортран , Бортеньев.pdf
    Дата28.05.2018
    Размер2.24 Mb.
    Формат файлаpdf
    Имя файласовременный фортран , Бортеньев.pdf
    ТипДокументы
    #19729
    страница18 из 49
    1   ...   14   15   16   17   18   19   20   21   ...   49
    161

    О. В. Бартеньев. Современный ФОРТРАН
    пренебрежение такой ошибкой приводит к созданию неработоспособных программ, например следующий цикл является бесконечным, поскольку 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 if(abs(x - 1.0) < 1.0e-5) exit
    ! x практически равен 1.0 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
    x
    2 1
    Рис. 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

    5. Выражения, операции и присваивание
    5.4. Приоритет выполнения операций
    Когда арифметические, символьные, логические операции и операции отношения присутствуют в одном выражении (такая смесь может быть, например, в логическом выражении), приоритет выполнения операций таков (дан в порядке убывания):
    1)
    любая заданная или перегруженная одноместная операция;
    2)
    арифметические операции;
    3)
    символьная операция конкатенации;
    4)
    операции отношения;
    5)
    логические операции;
    6)
    любая заданная или перегруженная двуместная операция.
    В табл. 5.2 встроенные операции Фортрана расположены в порядке убывания приоритета.
    Таблица 5.2. Приоритет выполнения встроенных операций
    ** *
    /
    +
    -
    // .EQ.,
    ==
    .NE., /=
    .LT., <
    .LE., <=
    .GT., >
    .GE., >=
    .NOT. .AND. .OR.
    .XOR.
    .EQV.
    .NEQV.
    Замечание. Каждаяячейка таблицы содержит операции с равным приоритетом.
    5.5. Константные выражения
    В операторах объявления Фортрана могут появляться выражения
    (например, при задании значений именованных констант), но такие выражения должны быть инициализирующими и константными, например: integer, parameter :: n = 10, m = n / 2 real a(m, n), b(2 * n)
    ! n / 2 и 2 * n - примеры константных выражений
    В общем случае константное выражение - это выражение, в котором все операции встроенные, а каждый простой элемент - это:

    константное выражение, заключенное в скобки;

    константа или подобъект константы, в котором каждый индекс сечения или граница подстроки является константным выражением;

    конструктор массива, в выражениях которого (включая границы и шаги) каждый простой член является константным выражением или переменной неявного цикла;
    167

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

    конструктор структуры, компоненты которого являются константными выражениями;

    обращение к встроенной элементной или преобразовывающей функции, все параметры в котором являются константными выражениями;

    обращение к встроенной справочной функции (кроме функций PRE-
    SENT, ASSOCIATED или ALLOCATED), в котором каждый параметр - это либо константное выражение, либо переменная, о которой выдается справка. Причем границы переменной, о которой выдается справка, не должны быть подразумеваемыми (случай массива или строки, перенимающей размер) или заданы с помощью оператора ALLOCATE или путем прикрепления ссылки.
    Именованным константам (объектам с атрибутом PARAMETER) могут быть присвоены значения только инициализирующих константных выражений. Значения таких выражений вычисляются при компиляции, и поэтому на них накладываются дополнительные ограничения:

    допускается возведение в степень лишь с целым показателем;

    аргументы и результаты встроенных элементных функций должны быть целого или текстового типа;

    из преобразовывающих функций допускаются только REPEAT, RE-
    SHAPE, SELECTED_INT_KIND, SELECTED_REAL_KIND, TRANSFER и TRIM.
    Каждый элемент инициализирующего выражения должен быть определен в предшествующем операторе объявления или левее в том же самом операторе объявления.
    Пример: character(*), parameter :: st(3) = (/ 'Январь', 'Февраль', 'Март' /) integer, parameter :: n = len_trim(st(2))
    5.6. Описательные выражения
    При задании в процедурах параметров разновидностей типов, границ массивов и текстовых длин объектов данных, а также при задании результатов функций могут наряду с константными использоваться скалярные, неконстантные выражения. Такие выражения называются
    описательными и содержат ряд ограничений:

    они могут зависеть только от тех значений, которые определены при входе в процедуру;

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

    5. Выражения, операции и присваивание
    В состав описательных выражений могут входить конструкторы массивов, производных типов и обращения к встроенным функциям. Но последние ограничены:

    элементными функциями с параметрами и результатом целого или текстового типа;

    функциями REPEAT, RESHAPE, TRANSFER и TRIM с параметрами целого или текстового типа;

    справочными функциями, кроме функций PRESENT, ASSOCIATED и ALLOCATED, при условии, что величина, информация о которой выдается, не зависит от выделения памяти и прикрепления ссылки.
    В обращении к справочной функции исследуемый объект может быть доступен посредством use-ассоциирования или ассоциирования через носитель или может быть объявлен в том же программном компоненте, но обязательно до его использования в справочной функции. На элемент массива, объявляемого в программном компоненте, можно ссылаться только после описания его границ.
    Пример: function fun(x, y, lob) real x
    ! Прежде объявляем x real(kind(x)) y, fun
    ! Теперь можно употребить x в описательном integer lob(2)
    ! выражении real, dimension( lob(1) : max(lob(2), 10) ) :: z real wz(lob(2) : size(z))
    ! Параметр разновидности типа переменной y и результирующей переменной
    ! fun, границы массивов z и wz задаются описательными выражениями.
    5.7. Присваивание
    Присваивание является оператором, в результате выполнения которого переменная получает значение расположенного в правой части оператора присваивания выражения. Переменная, получающая значение выражения, может быть как скаляром, так и массивом. В результате присваивания значения могут получать как объекты, так и их подобъекты, например элементы массивов, подстроки, компоненты переменных производных типов, сечения массивов.
    Синтаксис оператора:
    var = expr
    где var - имя переменной; expr - выражение.
    В соответствии со стандартом в случае встроенного присваивания типы переменной var и выражения expr должны соответствовать друг другу:

    результат арифметического выражения может быть присвоен числовой переменной. Если переменная и выражение имеют разные числовые
    169

    О. В. Бартеньев. Современный ФОРТРАН
    типы, то тип результата выражения приводится к типу переменной, которой присваивается результат, например: complex :: z = (-2.0, 3.0) integer k k = z * z print *, k
    ! -5

    результат логического выражения может быть присвоен логической переменной;

    результат символьного выражения может быть присвоен только символьной переменной;

    переменной производного типа можно присвоить значение выражения данного типа, например: type pair real x, y end type pair type(pair) :: p1, p2 = pair(1.0, 2.0) p1 = p2 p2 = pair(-2.0, -5.0)
    Правда, как мы уже видели, CVF и FPS имеют расширения по отношению к стандарту языка: логической переменной можно присвоить результат целочисленного выражения и, наоборот, числовой переменной можно присвоить результат логического выражения.
    Можно, однако, выполнить перегрузку присваивания. Например, можно задать оператор присваивания, в котором var имеет числовой, а expr - символьный тип. Или задать присваивание, при котором переменной производного типа присваивается результат выражения иного типа.
    Перегрузка присваивания выполняется так:

    составить подпрограмму sub с двумя обязательными параметрами x и y, причем параметр x должен иметь вид связи OUT, параметр y - IN.
    В результате работы подпрограммы определяется значение x;

    используя оператор INTERFACE ASSIGNMENT(=), связать подпрограмму sub с оператором присваивания. Тогда подпрограмма будет вызываться каждый раз, когда var имеет такой же тип, как и x, а тип expr совпадает с типом параметра y, т. е. присваивание x = y эквивалентно вызову call sub(x, y).
    Пример. Присвоить целочисленной переменной сумму кодов символов строки. interface assignment(=) subroutine charti(n, ch) integer, intent(out) :: n character(*), intent(in) :: ch
    1   ...   14   15   16   17   18   19   20   21   ...   49


    написать администратору сайта