2010-09-14 4 views
22

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

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

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

Массив либо определенный

real, dimension(3, 3) :: a 

или

real, dimension(:), allocatable :: a 

ответ

42

Вы можете сделать это с помощью 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 присущие:

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

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

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 
+12

1) Большинство компиляторов теперь принимают нотацию Fortran 2003 [] для инициализации массивов, а не несколько неудобных (/ /). 2) Для простых случаев вы можете опустить транспонирование, указав значения в главном порядке: array = reshape ([1, 4, 7, 2, 5, 8, 3, 6, 9], shape (array)) –

+0

Я забыл упомянуть, что мы должны работать в Fortran 90. –

4

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

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!

13

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

В Fortran, каждый ранг соответствует другому признаку измененного типа данных. Но существует только один конструктор массива для массивов ранга 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), что дает желаемый эффект.

 Смежные вопросы

  • Нет связанных вопросов^_^