Fortran學習筆記5(數組Array)



數組的聲明方式

數組是組織數據的一種方式。用來記錄類型、性質相同的長串數據。不論定義多少維的數組,數據在內存中都是線狀儲存的。

一維數組

datatype   name(size)
! datatype 是數組的類型,有整型、實型、復型、邏輯型、自定義型
! name 數組的名字
! size 數組的大小

integer a(10)                  ! 第一種定義方法
integer,dimension(10)::a       !第二種定義方法
integer a                      !第三種定義方法,該方法先聲明類型,在定義大小
dimension a(10)

二維數組

integer a(2,3)              ! 最簡單的方法
integer,dimension(2,3)::a   ! 第二種方法
integer a                   ! 第三種方法
dimension a(10,10)

多維數組

Fortran最多可聲明高達7維數組。

integer a(2,2,2,...,2)
integer,dimension(2,2,2,...,2)::a
integer a
dimension a(2,2,2,...,2)

數組索引值的改變

Fortran中數組的索引值可以改變,只需要在聲明數組的時候注明特別賦值數組的坐標值范圍。如:

integer a(0:5)      ! 該數組的索引值為0,1,2,3,4,5
integer a(-2:2,0:4,-5:-1)  ! 這也是可以的,有木有覺得很強大?

自定義類型的數組定義

直接給出例子:

Type::person
   real::height,weight
   character(len=80)::name
 End type

 Type(person)::a(10)
 ...
 ...
 a(2)%height=180.0    !在變量后面加上%來使用變量中的元素
 a(2)%weight=70

對數組內容的設置

數組內容的設置,既可以的那個元素設置,也可以對整個數組操作,還可以對數組中的部分判斷操作。

利用“隱含式”循環設置數組初值

integer a(5)
data a /1,2,3,4,5/
integer a(5)
data a/5*3/   ! 5*3表示53.a(1)=3,a(2)=3,a(3)=3,a(4)=3,a(5)=3
integer a(5)
integer i
data(a(i),i=2,4)/2,3,4/    !設定a(2)=2,a(3)=3,a(4)=4;a(1)、a(5)沒有設定
integer a(2,2)
data ((a(i,j),j=1,2),i=1,2)=/1,2,3,4/
integer::a(5)=(/1,2,3,4,5/)    !括號和除號之間不能有空格
integer::i
integer::a(5)=(/1,(2,I=2,4),5/) !a(1)=1,a(2)=2,a(3)=2,a(4)=2,a(5)=5
integer::i
integer::a(5)=(/(i,i=1,5)/)

對整個數組操作

這個功能是Fortran90添加的,在Fortran77中不適用。

integer::a(5)
a=5   ! 最后得到a的五個元素都等於5
integer::a(5,5),b(5,5),c(5,5)
c=a+b       !  相當於c(i,j)=a(i,j)+b(i,j)
c=a-b       !  相當於c(i,j)=a(i,j)-b(i,j)
c=a*b       !  相當於c(i,j)=a(i,j)*b(i,j)
c=a/b       !  相當於c(i,j)=a(i,j)/b(i,j)
a=sin(b)    !  相當於a(i,j)=sin(b(i,j))
c=a>b       !  當a(i,j)>b(i,j)時,c(i,j)=.true.,否則c(i,j)=.Flase.

對部分數組的操作

除了一次對整個數組進行操作之外,Fortran90還提供一次只挑出部分數組來操作的功能。取出部分數組的語法看起來有點像隱含式循環。

a(3:5)=5 !a(3)=5,a(4)=5,a(5)=5 a(3:)=5 !a(3)=5,a(4)=5,...,a(n)=5 a(3:5)=/3,4,5/ !a(3)=3,a(4)=4,a(5)=5 a(13)=b(2:4) !a(1)=b(2),a(2)=b(3),a(3)=b(4) a(1:5:2)=3 !a(1)=3,a(3)=3,a(5)=3,后面的2表示循環增量 a(1:10)=a(10:1:-1) ! 將a的值翻轉 a(:)=b(:,2) ! a的元素與b的2列的元素對應 a(:,:)=b(:,1,:)a的元素與b的1,3維元素對應相等
where函數

where命令經過邏輯判斷來設定數組的一部分元素。where可以嵌套,也可以多重判斷。where還可以命名,命名的where塊要在結束時加上名字,以表明結束的是哪一個where。並且,where只用來數組賦值,不能用來干其他事。並且同一個where塊中涉及運算的數組大小相同。

program main
    implicit none
    integer ::i
    real::a(10)=(/ (i,i=1,10) /)
    real::b(10)
    where (a<3)
        b=1
        elsewhere(a<5)
            b=2
            elsewhere(a<8)
                b=3
                elsewhere
                    b=4
    end where
    write(*,100)a
    write(*,101)b
100  format(T5,'Matrix A is : ',/,5(F6.2),' ')
101  format(T5,'Matrix B is : ',/,5(F6.2),' ')
end program

以下摘自彭國倫《Fortran95程序設計》

name: where(a<5)  ! where模塊可以取名字
b=a
end where name    ! 有取名字的where結束時也要賦值名字

where(a<5)        ! where可以嵌套
   where(a/=2)
      b=3
   elsewhere
      b=1
   end where
else where
   b=0
end where
Forall函數

Forall的語法為:

Forall(triple1[,triple2[,triple3...]],mask)
......
end forall ! mask是條件限制,滿足該條件的數組元素進行Forall操作

例如:

integer::a(20,5)
integer::i,j
forall(i=2:20:3,j=1:5)
    a(i,j)=i+j
end forall

Forall描述的程序模塊如果只有一行代碼,可以省略end Forall,把程序終結跟在Forall后面,寫在同一行。下面給出幾個例子。

integer::i,j
integer::a(20,10)
......
......
forall (i=1:5,j=2:8:2,a(i,j)<10)  ! 只處理a中小於10的元素
     a(i,j)=1
end forall

forall(i=2:13:3,j=1:5,((i>j).AND.a(i,j)>0)) a(i,j)=i**2+j**2

Forall可以寫成多層嵌套,它里面也只能出現跟設置數組數值相關的命令程序,還可以在Forall中使用where,但是,不能再where中使用Forall

下面給出一個例子,要求生成一個20*20的矩陣。該矩陣是一個帶狀矩陣。主對角元為8,上次一級為6,再次一級為0,再次一級為4,如此生成。下對角元和上對角元相同,只是把數字換成7,5,3,1。

program main
    implicit none
    integer::i,j,k
    integer::a(20,20)
    !數組置零
    a(:,:)=0
    Do k=-8,8,2
        if(k<0)then
            forall(i=1:20,j=1:20,i==j+k)     a(i,j)=k+9     
!請注意,Fortran在循環的過程中總是先循環最內層,所以這里i代表列,j代表行。不能搞反了。
        end if
        if(k>=0)then
            forall(i=1:20,j=1:20,i==j+k)     a(i,j)=-k+8
        end if
    End Do
    write(*,100)a

100      format(T5,'矩陣為:',/,20(I2),' ')

end program

數組的保存規則

一個數組不論它是什么形狀,它的元素在內存中的分布都是連續的。一維數組按順序排列,多維數組在內存中按照“Column Major”的方法來排列。所謂“Column Major”總結起來就是先列后行,先低維在高維。在循環的過程中,要按照低維循環在內,高維循環在外的方式。

integer::a(2,2,2)
! 排列順序為:
a(1,1,1)-a(2,1,1)-a(1,2,1)-a(2,2,1)-a(1,1,2)-a(2,1,2)-a(1,2,2)-a(2,2,2)

假設聲明了一個n維數組A(D1,D2,…,Dn),設 Sn=D1D2Dn ,則 A(d1,d2,d3,...,dn) 在第 1+(d11)+(d21)S1++(dn1)Sn1 個位置。

如果聲明的n維數組有設定每一維的起始值 A(S1:E1,S2,E2,,Sn:En) ,設 Mn=(E1S1+1)(E2S2=1)(EnSn+1) ,則 A(d1,d2,d3,.dn) 在第 1+(d1S1)+(d2S2)M1++(dnSn)Mn1 個位置。


可變大小的數組

Fortran77中沒有可變大小的數組。Fortran90添加了可變大小的數組。使用可變大小的數組時要經過兩個步驟。第一步是聲明,在聲明的時候要加上ALLOCATEBLE 。數組的大小用冒號代表。第二步是確定數組的大小。

allocate命令從內存中獲得一定空間,deallocate釋放掉該空間。

program main
    implicit none
    integer::size=0,error=0
    integer,parameter::onemb=1024*1024
    character,allocatable::a(:)

    do while(.true.) size=size+onemb allocate(a(size),stat=error) if(error/=0)exit write(*,"('Allocate ',I10,' bytes')")size write(*,"(F10.2,' Mb used')")real(size)/real(onemb) deallocate(a) end do stop end program

allocated用來檢查一個可變大小的矩陣是否已經配置了內存,它會返回一個邏輯值。

if(.not. allocated(a))then
    allocate(a(5))
end if


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM