Подтвердить что ты не робот

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

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

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

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

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

real, dimension(3, 3) :: a

или

real, dimension(:), allocatable :: a
4b9b3361

Ответ 1

Вы можете сделать это с помощью reshape и shape внутренности. Что-то вроде:

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

вам также понадобится transpose intrinsic:

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

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

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

Ответ 2

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

В 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), давая желаемый эффект.

Ответ 3

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

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 of (/(/1,2,3/),(/4,5,6/),(/7,8,9/)/) - 9, а не 3 3!