Как инициализировать двумерные массивы в Фортране

В C вы можете легко инициализировать массив, используя синтаксис фигурных скобок, если я правильно помню:

int* a = new int[] { 1, 2, 3, 4 };

Как вы можете сделать то же самое в Fortran для двумерных массивов, когда вы хотите инициализировать матрицу с конкретными тестовыми значениями для математических целей? (Без необходимости вдвойне индексировать каждый элемент в отдельных выражениях)

Массив определяется либо

real, dimension(3, 3) :: a

или же

real, dimension(:), allocatable :: a

4 ответа

Решение

Вы можете сделать это, используя встроенную форму. Что-то вроде:

INTEGER, DIMENSION(3, 3) :: array
array = reshape((/ 1, 2, 3, 4, 5, 6, 7, 8, 9 /), shape(array))

Но запомни колонку-мажорный порядок. Массив будет

1   4   7
2   5   8
3   6   9

после изменения формы

Итак, чтобы получить:

1   2   3
4   5   6
7   8   9

вам также нужно транспонировать внутреннее:

array = transpose(reshape((/ 1, 2, 3, 4, 5, 6, 7, 8, 9 /), shape(array)))

Для более общего примера (выделяемый двумерный массив с разными размерами) требуется встроенный размер:

PROGRAM main

  IMPLICIT NONE

  INTEGER, DIMENSION(:, :), ALLOCATABLE :: array

  ALLOCATE (array(2, 3))

  array = transpose(reshape((/ 1, 2, 3, 4, 5, 6 /),                            &
    (/ size(array, 2), size(array, 1) /)))

  DEALLOCATE (array)

END PROGRAM main

Для многомерных массивов (ранга>1) способ Фортрана для инициализации отличается от C-решения, поскольку в C многомерные массивы являются просто массивами массивов и т. Д.

В Фортране каждый ранг соответствует другому атрибуту измененного типа данных. Но существует только один конструктор массива для массивов ранга 1. По этим двум причинам инициализация через конструктор массива требует RESHAPE внутренняя функция.

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

Например, в случае с примером в первом ответе можно написать:

INTEGER, DIMENSION(3, 3) :: array=reshape( (/ 1, 2, 3, &
                                              4, 5, 6, &
                                              7, 8, 9 /), &
                                           shape(array), order=(/2,1/) )

получение заполнения матричного массива точно в порядке, указанном строками кода.

Массив (/2, 1/) форсирует индекс столбца (2) иметь приоритет по индексу строки (1), дающий желаемый эффект.

Инициализация массива может быть выполнена в самом объявлении массива, как показано ниже:

program test
 real:: x(3) = (/1,2,3/)
 real:: y(3,3) = reshape((/1,2,3,4,5,6,7,8,9/), (/3,3/))
 integer:: i(3,2,2) = reshape((/1,2,3,4,5,6,7,8,9,10,11,12/), (/3,2,2/))

end program test

Меня удивляет что

 real:: y(3,3) = (/(/1,2,3/),(/4,5,6/),(/7,8,9/)/)

не принимается компилятором (пробовал g95, gfortran). Оказывается, что shape из(/(/1,2,3/),(/4,5,6/),(/7,8,9/)/) является 9 и не 3 3!

**Real, Dimension(1:2,1:3)::Arr**

Определяет массив из 2 строк и 3 столбцов, строк с 1 по 2 и столбцов с 1 по 3.

Другие вопросы по тегам