arrays - resueltos - Cómo inicializar matrices bidimensionales en Fortran
problemas resueltos de programación en fortran 95 pdf (3)
La inicialización de la matriz se puede hacer en la declaración de declaración de la matriz, 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/)/)
No es aceptado por el compilador (probado g95, gfortran). Resulta que la shape
de (/(/1,2,3/),(/4,5,6/),(/7,8,9/)/)
es 9
y no 3 3
!
En C puedes inicializar fácilmente una matriz usando la sintaxis de llaves, si recuerdo correctamente:
int* a = new int[] { 1, 2, 3, 4 };
¿Cómo puede hacer lo mismo en Fortran para matrices bidimensionales cuando desea inicializar una matriz con valores de prueba específicos para propósitos matemáticos? (Sin tener que indexar doblemente cada elemento en declaraciones separadas)
La matriz está definida por
real, dimension(3, 3) :: a
o
real, dimension(:), allocatable :: a
Para matrices multidimensionales (rango> 1), la forma de inicialización de Fortran difiere de la solución C porque en C las matrices multidimensionales son solo 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 matrices, para las matrices de rango 1. Por estas dos razones, la inicialización a través del constructor de arreglos requiere la función RESHAPE
.
Además de lo que ya se ha respondido, hay una forma más directa de ingresar el valor de una matriz por fila en lugar de por columna: remodelar tiene un argumento opcional ORDER
que puede usarse para modificar el orden de llenado del elemento de lo multidimensional. array con las entradas del constructor de array.
Por ejemplo, en el caso del ejemplo en la primera respuesta, uno podría escribir:
INTEGER, DIMENSION(3, 3) :: array=reshape( (/ 1, 2, 3, &
4, 5, 6, &
7, 8, 9 /), &
shape(array), order=(/2,1/) )
obteniendo el relleno de la matriz matricial exactamente en el orden mostrado por las líneas de código.
La matriz (/2, 1/)
obliga a que el índice de la columna (2)
tenga prioridad sobre el índice de la fila (1)
, dando el efecto deseado.
Puedes hacer eso usando reshape y reshape shape intrínsecos. Algo como:
INTEGER, DIMENSION(3, 3) :: array
array = reshape((/ 1, 2, 3, 4, 5, 6, 7, 8, 9 /), shape(array))
Pero recuerda el orden de la columna principal. La matriz será
1 4 7
2 5 8
3 6 9
después de remodelar.
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)))
Para un ejemplo más general (matriz 2D asignable con diferentes dimensiones), se necesita un size intrínseco:
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