數組的聲明方式
數組是組織數據的一種方式。用來記錄類型、性質相同的長串數據。不論定義多少維的數組,數據在內存中都是線狀儲存的。
一維數組
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表示5個3.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(1;3)=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=D1∗D2∗⋯∗Dn ,則A(d1,d2,d3,...,dn) 在第1+(d1−1)+(d2−1)∗S1+⋯+(dn−1)∗Sn−1 個位置。如果聲明的n維數組有設定每一維的起始值
A(S1:E1,S2,E2,⋯,Sn:En) ,設Mn=(E1−S1+1)∗(E2−S2=1)∗⋯∗(En−Sn+1) ,則A(d1,d2,d3,⋯.dn) 在第1+(d1−S1)+(d2−S2)∗M1+⋯+(dn−Sn)∗Mn−1 個位置。
可變大小的數組
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