Comment initialiser des tableaux en deux dimensions en Fortran
-
02-10-2019 - |
Question
En C, vous pouvez facilement initialiser un tableau en utilisant la syntaxe des accolades, si je me souviens bien:
int* a = new int[] { 1, 2, 3, 4 };
Comment pouvez-vous faire la même chose dans Fortran pour les tableaux en deux dimensions lorsque vous souhaitez initialiser une matrice avec des valeurs de test spécifiques à des fins mathématiques? (Sans avoir à indexer doublement tous les éléments sur les états séparés)
Le réseau est soit définie par
real, dimension(3, 3) :: a
ou
real, dimension(:), allocatable :: a
La solution
Vous pouvez le faire en utilisant Reshape et les valeurs intrinsèques de forme. Quelque chose comme:
INTEGER, DIMENSION(3, 3) :: array
array = reshape((/ 1, 2, 3, 4, 5, 6, 7, 8, 9 /), shape(array))
Mais rappelez-vous l'ordre des colonnes-major. Le tableau sera
1 4 7
2 5 8
3 6 9
après le formage.
Donc, pour obtenir:
1 2 3
4 5 6
7 8 9
vous devez également intrinsèque Transpose:
array = transpose(reshape((/ 1, 2, 3, 4, 5, 6, 7, 8, 9 /), shape(array)))
Par exemple plus générale (tableau allouable 2D avec des dimensions différentes), on a besoin de taille intrinsèque:
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
Autres conseils
Pour les tableaux multidimensionnels (rang 1>), la façon dont Fortran diffère d'initialisation de la solution C, car dans des tableaux multidimensionnels C ne sont que des tableaux de tableaux de etc.
Fortran, chacun correspond à un rang attribut différent du type de données modifié. Mais il n'y a qu'un seul constructeur de tableau, pour les tableaux de rang 1. A partir de ces deux raisons, l'initialisation par le constructeur de tableau nécessite la fonction RESHAPE
intrisic.
En plus de ce qui a déjà reçu une réponse, il est d'une manière plus directe d'entrer la valeur d'une matrice ligne par ligne au lieu que par colonne: reshape a un argument optionnel ORDER
qui peut être utilisé pour modifier l'ordre de remplissage de l'élément du tableau multidimensionnel avec les entrées du constructeur de tableau.
Par exemple, dans le cas de l'exemple dans la première réponse, on pourrait écrire:
INTEGER, DIMENSION(3, 3) :: array=reshape( (/ 1, 2, 3, &
4, 5, 6, &
7, 8, 9 /), &
shape(array), order=(/2,1/) )
obtenir le remplissage de la matrice de la matrice exactement dans l'ordre indiqué par les lignes de code.
Les forces de (/2, 1/)
de réseau l'indice de colonne de (2)
d'avoir priorité sur l'index de ligne (1)
, ce qui donne l'effet recherché.
initialisation Array peut être fait dans la déclaration de déclaration de tableau lui-même, comme indiqué ci-dessous:
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
Il me surprend que
real:: y(3,3) = (/(/1,2,3/),(/4,5,6/),(/7,8,9/)/)
pas accepté par le compilateur (essayé G95, gfortran). Il se trouve que le shape
de
(/(/1,2,3/),(/4,5,6/),(/7,8,9/)/)
est 9
et non 3 3
!