Как инициализировать двухмерные массивы в Fortran
-
02-10-2019 - |
Вопрос
В C вы можете легко инициализировать массив, используя синтаксис Curly Braces, если я правильно помню:
int* a = new int[] { 1, 2, 3, 4 };
Как вы можете сделать то же самое в Fortran для двухмерных массивов, когда вы хотите инициализировать матрицу с конкретными значениями тестирования для математических целей? (Без необходимости вдвойне индексировать каждый элемент на отдельных операторах)
Массив определяется либо
real, dimension(3, 3) :: a
или
real, dimension(:), allocatable :: a
Решение
Вы можете сделать это с помощью Решап и форма Внутренние. Что-то вроде:
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 многомерных массивах представляют собой просто массивы массивов и т. Д.
В Fortran каждый ранг соответствует другому атрибуту измененного типа данных. Но есть только один конструктор массива, для массивов Rank-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
!