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

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

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

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

массив определен как

real, dimension(3, 3) :: a

или

real, dimension(:), allocatable :: a

3 ответов


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

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)))

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

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) способ Fortran для инициализации отличается от решения C, потому что в C многомерные массивы-это просто массивы массивов etc.

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

В дополнение к тому, что есть уже был дан ответ, есть более прямой способ ввода значения матрицы по строке, а не по столбцу: 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/)/)

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