2010-09-14 18 views
22

In C si può facilmente inizializzare un array utilizzando la sintassi parentesi graffe, se non ricordo male:come inizializzare array bidimensionali in Fortran

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

Come si può fare lo stesso in Fortran per bidimensionale array quando si desidera inizializzare una matrice con valori di test specifici per scopi matematici? (Senza dover doppiamente indice ogni elemento di dichiarazioni separate)

La matrice può essere definito sia da

real, dimension(3, 3) :: a 

o

real, dimension(:), allocatable :: a 

risposta

42

Si può fare usando reshape e shape intrinseci. Qualcosa di simile:

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

Ma ricorda l'ordine delle colonne. L'array sarà

1 4 7 
2 5 8 
3 6 9 

dopo il rimodellamento.

Quindi, per ottenere:

1 2 3 
4 5 6 
7 8 9 

hai bisogno anche di transpose intrinseca:

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

Per esempio più generale (matrice 2D allocatable con dimensioni diverse), si ha la necessità size intrinseca:

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 maggior parte dei compilatori ora accetta la notazione di Fortran 2003 [] per inizializzare gli array, invece di un po 'scomodo (/ /). 2) Per casi semplici puoi omettere la trasposizione fornendo i valori nell'ordine delle colonne: array = reshape ([1, 4, 7, 2, 5, 8, 3, 6, 9], shape (array)) –

+0

Ho dimenticato di menzionare che siamo tenuti a lavorare in Fortran 90. –

4

L'inizializzazione di array può essere eseguita nell'array d ICHIARAZIONE dichiarazione stessa, come illustrato di seguito:

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 

mi sorprende che

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

è non accettato dal compilatore (provato G95, gfortran). Si scopre che il shape di (/(/1,2,3/),(/4,5,6/),(/7,8,9/)/) è 9 e non 3 3!

13

Per multidimensionale (ranking> 1) array, il modo Fortran per l'inizializzazione differisce dalla soluzione C perché C array multidimensionali sono solo array di array di ecc

In FORTRAN, ogni grado corrisponde ad un attributo diverso del tipo di dati modificati. Ma esiste un solo costruttore di array, per gli array rank-1. Da questi due motivi, l'inizializzazione tramite il costruttore di array richiede la funzione intriseca RESHAPE.

Oltre a ciò che è già stato risposto, esiste un modo più diretto di immettere il valore di una matrice per riga invece che per colonna: reshape ha un argomento opzionale che può essere utilizzato per modificare l'ordine di riempimento del elemento della matrice multidimensionale con le voci del costruttore di array.

Ad esempio, nel caso dell'esempio nella prima risposta, si potrebbe scrivere:

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

ottenere il riempimento della matrice esattamente nell'ordine indicato dalle linee di codice.

L'array (/2, 1/) impone all'indice di colonna (2) di avere la precedenza sull'indice di riga (1), dando l'effetto desiderato.

Problemi correlati