Как инициализировать двумерные массивы в Фортране
В 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.