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

StackOverflow https://stackoverflow.com/questions/3708307

Вопрос

В 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!

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top