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

  • 4.10. Использование массивов

  • 4.11. Массив как результат функции

  • 4.12. Встроенные функции для массивов

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


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

    4. Массивы
    Пример. Даны матрицы a и b разной формы. В какой из них первый отрицательный элемент последнего столбца имеет наибольшее значение? program neg2 interface !
    Процедура, формальными параметрами которой integer function FindNeg(c)
    ! являются перенимающие форму массивы, integer :: c(:, :)
    ! должна обладать явным интерфейсом end function FindNeg end interface integer a(4, 5), b(-1:7, -1:8) integer nga, ngb, ngmax
    ! nga и ngb - соответственно последние a = 1; a(3, 5) = -2
    ! отрицательные элементы матриц a и b b = 2; b(2, 8) = -3 nga = FindNeg(a)
    ! Ищем nga и ngb ngb = FindNeg(b) if(nga == 0) print *, 'В последнем столбце матрицы а нет отрицательных элементов' if(ngb == 0) print *, 'В последнем столбце матрицы b нет отрицательных элементов' ngmax = max(nga, ngb)
    ! Если не все матрицы имеют отрицательный элемент в последнем столбце - STOP if(ngmax == 0) stop if(nga == ngmax) print *, 'В матрице a' if(ngb == ngmax) print *, 'В матрице b' end integer function FindNeg(c)
    ! Возвращает первый отрицательный элемент integer :: c(:, :)
    ! последнего столбца матрицы c integer cols, i
    FindNeg = 0 cols = ubound(c, dim = 2)
    ! Номер последнего столбца в массиве c do i = lbound(c, 1), ubound(c, 1) if(c(i, cols) < 0) then
    FindNeg = c(i, cols)
    ! Вернем найденный отрицательный элемент return end if end do end function FindNeg
    Результат:
    В матрице a
    4.9.3. Массивы, перенимающие размер
    В перенимающем размер массиве - формальном параметре вместо верхней границы последней размерности проставляется звездочка (*).
    (Таким же образом задаются перенимающие длину строки.) Остальные границы должны быть описаны явно. Перенимающий размер массив может отличаться по рангу и форме от соответствующего массива - фактического параметра. Фактический параметр определяет только размер массива - формального параметра. Например:
    135

    О. В. Бартеньев. Современный ФОРТРАН
    real x(3, 6, 5), y(4, 10, 5) call asub(x, y) subroutine asub(a, b) real a(3, 6, *), b(0:*) print *, size(a, 2)
    ! 6 print *, lbound(a, 3), lbound(b)
    ! 1 0
    Перенимающие размер массивы не имеют определенной формы.
    Это можно проиллюстрировать примером: real x(7) call assume(x) subroutine assume(a) real a(2, 2, *)
    При такой организации данных между массивами x и a устанавливается соответствие: x(1) = a(1, 1, 1) x(2) = a(2, 1, 1) x(3) = a(1, 2, 1) x(4) = a(2, 2, 1) x(5) = a(1, 1, 2) x(6) = a(2, 1, 2) x(7) = a(1, 2, 2) т. е. в массиве a нет элемента a(2, 2, 2). (Размер массива a определяется размером массива x и равен семи.)
    Так как перенимающие размер массивы не имеют формы, то нельзя получить доступ ко всему массиву, передавая его имя в процедуру.
    (Исключение составляют процедуры, не требующие форму массива, например встроенная функция LBOUND.) Так, нельзя использовать только имя перенимающего размер массива в качестве параметра встроенной функции SIZE, но можно определить протяженность вдоль фиксированной
    (т. е. любой, кроме последней) размерности.
    Можно задать сечения у перенимающего размер массива. Однако в общем случае надо следить, чтобы все элементы сечения принадлежали массиву. Так, для массива a из последнего примера нельзя задать сечение
    a(2, 2, 1:2), поскольку в массиве a нет элемента a(2, 2, 2).
    Необходимо следить, чтобы при работе с перенимающими размер массивами не происходило обращений к не принадлежащим массиву ячейкам памяти. Так, следующий фрагмент будет выполнен компьютером, но исказит значение переменной d: program bod integer b(5) /5*11/, d /-2/ call testb(b)
    136

    4. Массивы write(*, *) d
    ! Вместо ожидаемого -2 имеем 15 end subroutine testb(b) integer b(*)
    ! Массив, перенимающий размер b(6) = 15
    ! По адресу b(6) находится переменная d end
    Учитывая отмеченные недостатки в организации перенимающих размер массивов (отсутствие формы, возможность выхода за границы, невозможность использования в качестве результата функции), следует применять в качестве формальных параметров массивы заданной формы или массивы, перенимающие форму.
    4.10. Использование массивов
    Фортран позволяет работать с массивами и сечениями массивов так же, как и с единичными объектами данных:

    массивам и их сечениям можно присваивать значения;

    массивы (сечения массивов) можно применять в качестве операндов в выражениях с арифметическими, логическими операциями и операциями отношения. Результат выражения, которое содержит массивы и/или сечения массивов, присваивается массиву (сечению). В результате присваивания получается массив (сечение), каждый элемент которого имеет значение, равное результату операций над соответствующими элементами операндов:
    массив |
    сечение = выражение

    массивы и сечения могут быть параметрами встроенных элементных функций (разд. 6.1), например SIN и SQRT. Элементные функции, получив массив (сечение) в качестве аргумента, выполняются последовательно для всех элементов массива (сечения).
    Правда, существует ограничение: используемые в качестве операндов массивы (сечения массивов) и массив (сечение), которому присваивается результат выражения, должны быть согласованы.
    Массивы (сечения) согласованы, если они имеют одинаковую форму.
    Так, согласованы массивы a(-1:6) и b(-1:6), массивы c(2:9) и b(-1:6). Всегда согласованы массив и скаляр.
    Пример:
    integer(2) a(5) /1, 2, 3, 4, 5/, a2(4, 7) /28*5/ integer(2) :: b(5) = (/ 1, 2, -2, 4, 3 /) integer(2) :: ic(5) = 1 character(1) d1(4) / 'a', 'c', 'e', 'g' / character(1) d2(4) / 'b', 'd', 'f', 'h' / character(4) d12(4) real(4) c(2) /2.2, 2.2/, d(2) /2.2, 3.3/, cd*8(2)
    137

    О. В. Бартеньев. Современный ФОРТРАН
    logical(1) g(3) / .true., .false., .true. / logical(1) h(3) / 3*.false. / ic = ic + 2 * (a - b) - 2
    ! Присваивание массива write(*, *) ic
    !
    -1
    -1 9
    -1 3 a2(3, 1:5) = a2(3, 1:5) - a
    ! Согласованные массив и сечение write(*, *) int(sqrt(real(a*b**2))) !
    1 2
    3 8
    6 write(*, *) exp(real(a/b))
    ! 2.718 2.718 3.68e-01 write(*, *) a**b
    !
    1 4
    0 256 125 d12 = d1 // '5' // d2 // '5' write(*, *) d12
    ! a5b5c5d5e5f5g5h5 write(*, *) mod(a, b)
    !
    0 0
    1 0
    2 write(*, *) sign(a, b)
    !
    1 2
    -3 4
    5 write(*, *) dim(a, b)
    !
    0 0
    5 0
    2 cd = dprod(c, d)
    ! 4.840 7.26 write(*, *) g .and. .not. h
    !
    T
    F
    T end
    4.11. Массив как результат функции
    Массив также может быть и результатом функции. Интерфейс к такой функции должен быть задан явно. Если функция не является ссылкой, то границы массива должны быть описательными выражениями, которые вычисляются при входе в функцию.
    Пример. Составить функцию, возвращающую массив из первых n положительных элементов передаваемого в нее массива. real, allocatable :: ap(:) real :: a(10) = (/ 1, -1, 2, -2, 3, -3, 4, -4, 5, -5 /) real :: b(10) = (/ 2, -1, 3, -2, 4, -3, 4, -4, 5, -5 /) integer n /3/ allocate(ap(n)) ap = fap(a, n) + fap(b, n)
    ! Вызов массивоподобной функции fap print '(1x, 10f5.1)', ap
    ! 3.0 5.0 7.0 contains function fap(a, n) integer :: n, k, i real :: fap(n)
    ! Результатом функции является массив real, dimension(:) :: a
    ! a - перенимающий форму массив fap = 0 k = 0 do i = 1, size(a) if(a(i) > 0) then k = k + 1 fap(k) = a(i)
    ! Формирование массива-результата if(k == n) exit end if end do
    138

    4. Массивы end function fap end
    Замечания:
    1. Если оформить функцию fap как внешнюю, то к ней нужно в вызывающей программной единице явно задать интерфейс: interface function fap(a, n) integer n real fap(n) real, dimension(:) :: a end function fap end interface
    2. Ту же задачу можно решить, не создавая довольно громоздкой функции
    fap, а дважды вызвав встроенную функцию PACK (разд. 4.12.4.2): ap = pack(a, a > 0) + pack(b, b > 0)
    Однако если длина возвращаемых функцией PACK массивов меньше n, часть элементов массива ap будет не определена, а результат - непредсказуем.
    Функции, возвращающие массив, называют массивоподобными
    функциями. Из примера видно, что массивоподобные функции могут быть, как и обычные функции, операндами выражений.
    4.12. Встроенные функции для массивов
    В Фортран встроено большое число функций, позволяющих:

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

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

    получать справочные данные о массиве (размер, форма и значения границ каждого измерения).
    Вызов любой функции для массивов может быть выполнен с ключевыми словами, в качестве которых используются имена формальных параметров.
    Вызов с ключевыми словами обязателен, если позиции соответствующих фактического и формального параметров не совпадают.
    Параметрами всех рассматриваемых в разделе функций могут быть и сечения массивов.
    Некоторые функции возвращают результат стандартного целого или логического типа. По умолчанию значение параметра разновидности для этих типов KIND равно четырем. Однако если задана опция компилятора
    /4I2 или директива $INTEGER:2, значение разновидности стандартного целого и логического типов будет равно двум.
    139

    О. В. Бартеньев. Современный ФОРТРАН
    Как и ранее, необязательные параметры функций обрамляются квадратными скобками.
    4.12.1. Вычисления в массиве
    ALL(mask [, dim]) - возвращает .TRUE., если все элементы логического массива mask вдоль заданного (необязательного) измерения dim истинны; в противном случае возвращает .FALSE.
    Результатом функции является логический скаляр, если mask одномерный массив или опущен параметр dim (в этом случае просматриваются все элементы массива mask). Иначе результатом является логический массив, размерность которого на единицу меньше размерности
    mask. Разновидности типа результата и mask совпадают.
    Параметр dim - целое константное выражение (1
    dimn, где n - размерность массива mask). Параметр dim, если он задан, означает, что действие выполняется по всем одномерным сечениям, которые можно задать по измерению с номером dim. Функция вычисляет результат для каждого из сечений и заносит в массив на единицу меньшего ранга с экстентами, равными экстентам по остальным измерениям. Так, в двумерном массиве mask(1:2, 1:3) по второму измерению (dim = 2) можно задать два одномерных сечения: mask(1, 1:3) и mask(2, 1:3). Поэтому для хранения результата функции ALL(mask, 2) следует использовать одномерный логический массив из двух элементов.
    ANY(mask [, dim]) - возвращает .TRUE., если хотя бы один элемент логического массива вдоль заданного (необязательного) измерения dim истинен; в противном случае функция возвращает .FALSE.
    Результат функции и действие параметра dim определяются по тем же правилам, что и для функции ALL.
    COUNT(mask [, dim]) - возвращает число элементов логического массива
    mask, имеющих значение .TRUE. вдоль заданного необязательного измерения dim. Результат функции имеет стандартный целый тип. Правила получения результата и действие параметра dim такие же, как и для функции ALL.
    Для функций ALL, ANY, COUNT:
    Пример 1: logical ar1(3), ar2(2)
    ! Массивы для хранения результатов logical mask(2, 3) / .true., .true., .false., .true., .false., .false. /
    ! Массив mask: .true.
    .false. .false.
    ! .true.
    .true. .false.
    ar1 = all(mask, dim = 1)
    ! Оценка элементов в столбцах массива print *, ar1
    ! T F F ar2 = all(mask, dim = 2)
    ! Оценка элементов в строках массива print *, ar2
    ! F F
    140

    4. Массивы print *, any(mask, dim = 1)
    ! T T F print *, any(mask, dim = 2)
    ! T T print *, count(mask, dim = 1)
    ! 2 1 0 print *, count(mask, dim = 2)
    ! 1 2 end
    Пример 2. Если хотя бы один элемент второго столбца матрицы a меньше нуля, напечатать число положительных элементов ее первой строки. integer a(4, 5) a = 2;
    ! Инициализация массива a(2, 2) = 0
    ! Теперь второй элемент второго столбца равен нулю a(1, 3) = -1
    ! Теперь третий элемент первой строки меньше нуля if(any(mask = a(:, 2) == 0)) print *, count(a(1, :) > 0) end
    ! 4
    MAXLOC(array [, dim][, mask]) - возвращает индексы максимального элемента массива array или максимальных элементов по заданному измерению dim. Значение каждого максимального элемента удовлетворяет заданным (необязательным) условиям mask. Если несколько элементов содержат максимальное значение, то берется первый по порядку их следования в array. Результат MAXLOC, если не задан параметр dim, записывается в одномерный массив, размер которого равен числу измерений array.
    Параметр mask является логическим массивом, форма которого совпадает с формой массива array. Массив mask может получаться в результате вычисления логического выражения. Если массив задан, то действие функции распространяется только на те элементы массива array, для которых значение mask равно .TRUE. Если же параметр mask опущен, то действие функции распространяется на все элементы массива array.
    Значения индексов берутся так, словно все нижние границы массива ar-
    ray равны единице. Если же маска такова, что наибольший элемент не может быть найден, то возвращаемые значения индексов превышают верхнюю границу каждой размерности массива array.
    Если параметр dim задан, то:

    массив-результат имеет ранг, на единицу меньший ранга массива array, и форму (d
    1
    , d
    2
    , ..., d
    dim - 1
    , d
    dim + 1
    , ..., d
    n
    ), где (d
    1
    , d
    2
    , ..., d
    n
    ) - форма массива
    array;

    если array имеет ранг, равный единице, то MAXLOC(array, dim [, mask]) возвращает то же, что и функция MAXLOC(array [, MASK = mask]); иначе значение элемента (s
    1
    , s
    2
    , ..., s
    dim - 1
    , s
    dim + 1
    , ..., s
    n
    ) результата функции MAXLOC(array, dim [, mask]) равно MAXLOC(array(s
    1
    , s
    2
    , ...,
    s
    dim - 1
    , s
    dim + 1
    , ..., s
    n
    ), [, MASK = mask(s
    1
    , s
    2
    , ..., s
    dim - 1
    , s
    dim + 1
    , ..., s
    n
    )]).
    141

    О. В. Бартеньев. Современный ФОРТРАН
    MINLOC(array [, dim][, mask]) выполняет те же действия, что и MAX-
    LOC, но для минимальных элементов массива array. Смысл параметров dim и mask такой же, что и для функции MAXLOC. Значения индексов берутся так, словно все нижние границы массива array равны единице. Если же маска такова, что наименьший элемент не может быть найден, то возвращаемые значения индексов превышают верхнюю границу каждой размерности массива array.
    Замечание. Необязательный параметр dim добавлен в функции MAXLOC и MINLOC стандартом 1995 г.
    Пример для функций MAXLOC и MINLOC: integer ir, maxf(1) integer arra(3, 3) /7, 9, -1, -2, 5, 0, 3, 6, 9/ integer, allocatable :: ar1(:)
    ! Массив arra: 7
    -2 3
    ! 9 5
    6
    ! -1 0
    9 ir = size(shape(arra))
    ! Ранг массива array (ir = 2) allocate(ar1(ir))
    ! Найдем в массиве array индексы наибольшего, но меньшего семи элемента ar1 = maxloc(arra, mask = arra < 7)
    ! Результатом выражения mask = arra < 7 является массив mask
    ! такой же формы, которую имеет и массив arra. Элементы массива mask имеют
    ! значение .TRUE., если соответствующий элемент массива arra меньше семи,
    ! и .FALSE. - в противном случае. Благодаря такой маске функция
    ! MAXLOC возвращает индексы максимального, но меньшего семи элемента
    ! Массив arra:
    7
    -2 3 Массив mask: .false.
    .true.
    .true.
    ! 9 5
    6 .false.
    .true.
    .true.
    ! -1 0
    9
    .true.
    .true.
    .false. print *, ar1
    ! 2 3 print *, minloc(arra, mask = arra > 0)
    ! 1 3 maxf = maxloc((/ 1, 4, 1, 4 /)) print *, maxf
    ! 2 (индекс первого максимума) print *, minloc((/ 1, 4, 1, 4 /))
    ! 1 (индекс первого минимума) end
    Пример для функции MAXLOC с параметром dim: integer(4), parameter :: m = 3, n = 5 real(4) :: a(m, n) integer ip(n) a = reshape((/
    3.0, 4.0, 5.0, 6.0, 7.0, &
    2.0,
    3.0,
    4.0, 5.0, 6.0, &
    1.0, 2.0, 3.0, 4.0,
    5.0 /), shape = (/ m, n /), order = (/ 2, 1 /))
    142

    4. Массивы ip = maxloc(array = a, mask = a < 5, dim = 1) print *, ip
    ! 1 1 2 3 0
    MAXVAL(array [, dim] [, mask]) - возвращает максимальное, удовлетворяющее необязательной маске mask значение целочисленного или вещественного массива array вдоль заданного необязательного измерения
    dim.
    Смысл параметра dim разъяснен при описании функции ALL, а параметра mask - при описании функции MAXLOC.
    Возвращаемое значение имеет тот же тип и разновидность типа, что и массив array. Если параметр dim опущен или массив array одномерный, то результатом функции MAXVAL является скаляр, в противном случае результатом является массив, ранг которого на единицу меньше ранга массива
    array.
    Если размер массива 0 или все элементы массива mask равны .FALSE., то функция MAXVAL возвращает наибольшее по абсолютной величине отрицательное допускаемое процессором число.
    MINVAL(array [, dim] [, mask]) - возвращает минимальное, удовлетворяющее необязательной маске mask значение целочисленного или вещественного массива array вдоль заданного необязательного измерения
    dim.
    Смысл параметра dim разъяснен при описании функции ALL, а параметра mask - при описании функции MAXLOC.
    Возвращаемое значение имеет тот же тип и разновидность типа, что и массив array. Если параметр dim опущен или массив array одномерный, то результатом функции MINVAL является скаляр, в противном случае результатом является массив, ранг которого на единицу меньше ранга массива
    array.
    Если размер массива 0 или все элементы массива mask равны .FALSE., то функция MINVAL возвращает наибольшее положительное допускаемое процессором число.
    Пример для функций MAXVAL и MINVAL: integer array(2, 3), isha(2), max integer, allocatable :: ar1(:), ar2(:) array = reshape((/1, 4, 5, 2, 3, 6/), (/2, 3/))
    ! Массив array: 1 5 3
    !
    4 2 6 isha = shape(array)
    ! isha = (2 3) allocate(ar1(isha(2))) !
    isha
    (2) = 3 - число столбцов в массиве allocate(ar2(isha(1)))
    ! isha(1) = 2 - число строк в массиве max = maxval(array, mask = array < 4) ! Возвращает 3 ar1 = maxval(array, dim = 1)
    ! Возвращает (4 5 6) ar2 = maxval(array, dim = 2)
    ! Возвращает (5 6) print *, minval(array, mask = array > 3) ! 4 (ключевое слово mask обязательно)
    1   ...   11   12   13   14   15   16   17   18   ...   49


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