2010-09-14 9 views
22

En C puede inicializar fácilmente una matriz usando la sintaxis de llaves, si no recuerdo mal:cómo inicializar matrices bidimensionales de Fortran

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

¿Cómo puede hacer lo mismo en Fortran para dos dimensiones matrices cuando desea inicializar una matriz con valores de prueba específicos para fines matemáticos? (Sin tener que doblemente índice de cada elemento en los estados separados)

La matriz se define por cualquiera de

real, dimension(3, 3) :: a 

o

real, dimension(:), allocatable :: a 

Respuesta

42

Se puede hacer que el uso de reshape y shape intrínsecos. Algo así como:

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

Pero recuerde el orden column-major. La matriz será

1 4 7 
2 5 8 
3 6 9 

después de la remodelación.

Así que para obtener:

1 2 3 
4 5 6 
7 8 9 

también necesita transpose intrínseca:

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

Por ejemplo más general (matriz 2D asignable con diferentes dimensiones), se necesita size intrínseca:

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) La mayoría de los compiladores ahora aceptan la notación Fortran 2003 [] para inicializar matrices, en lugar de la algo torpe (/ /). 2) Para casos simples, puede omitir la transposición proporcionando los valores en el orden de columna principal: array = remodelar ([1, 4, 7, 2, 5, 8, 3, 6, 9], forma (matriz)) –

+0

Olvidé mencionar que estamos obligados a trabajar en Fortran 90. –

4

La inicialización de la matriz se puede hacer en la matriz d eclaración declaración en sí, como se muestra a continuación:

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 

Me sorprende que

real:: y(3,3) = (/(/1,2,3/),(/4,5,6/),(/7,8,9/)/) 

es no aceptado por el compilador (tratado G95, gfortran). ¡Resulta que el shape de (/(/1,2,3/),(/4,5,6/),(/7,8,9/)/) es 9 y no 3 3!

13

Para multidimensional (rango> 1) arrays, la forma en Fortran para la inicialización difiere de la solución C, porque en C matrices multidimensionales son sólo matrices de matrices de etc.

En Fortran, cada rango corresponde a un atributo diferente del tipo de datos modificado. Pero solo hay un constructor de matriz, para matrices de rango 1. A partir de estos dos motivos, la inicialización a través del constructor de conjuntos requiere la función intrísica RESHAPE.

Además de lo que ya se ha respondido, hay una manera más directa de ingresar el valor de una matriz por fila en lugar de por columna: reshape tiene un argumento opcional ORDER que se puede usar para modificar el orden de llenado del elemento de la matriz multidimensional con las entradas del constructor de la matriz.

Por ejemplo, en el caso del ejemplo, en la primera respuesta, se podría escribir:

INTEGER, DIMENSION(3, 3) :: array=reshape((/ 1, 2, 3, & 
               4, 5, 6, & 
               7, 8, 9 /), & 
              shape(array), order=(/2,1/)) 

obtener el llenado de la matriz matriz exactamente en el orden que se muestra por las líneas de código.

La matriz (/2, 1/) obliga al índice de columna (2) a tener prioridad en el índice de fila (1), dando el efecto deseado.

Cuestiones relacionadas