【Fortran】一维数组(初级)
Fortran中的一维数组
数组是一组类型完全相同、且用单个名字来引用的变量或常量。
1) 数组声明
在声明数组大小时,应使用参数来声明,以保证程序后续易修改。
- 一维数组:长度与数组中个数相同,使用
( )
可以访问具体数值。声明语句如:
INTEGER,DIMENSION(10)::number ! 定义长度为10的整数型数组number,同理可换成其它类型
- 常量数组是指完全由常量组成的数组,可以通过数组构造器来定义。数组构造器的形式有
(/ /)
和[ ]
,以下两个数组是等效的:
(/ 1 , 2 , 3 , 4 , 5 /)
[ 1 , 2 , 3 , 4 , 5 ]
2) 数组初始化
在使用数组之前,一定要先对其初始化。
初始化方法主要有三种:
-
用赋值语句初始化;
- 元素较少的,直接赋值,如:
REAL , DIMENSION(10)::array1 array1 = [1. , 2. , 3. , 4. , 5. , 6. , 7. , 8. , 9. , 10. ]
- 元素较多,且有规律的,可结合
DO
循环语句,如:
REAL , DIMENSION(100)::array2 DO i = 1,100 array2( i ) = REAL( i ) END DO
- 数组中所有元素均为同一值,可直接赋值,如:
REAL , DIMENSION(10)::array3 array3 = 1.0 ! 所有元素均为1.0
-
使用类型声明语句初始化;
- 元素较少的,直接声明,如:
REAL , DIMENSION(10)::array4 = [1. , 2. , 3. , 4. , 5. , 6. , 7. , 8. , 9. , 10. ]
- 元素较多,且有规律的,可结合隐式
DO
循环语句,如:
REAL , DIMENSION(100)::array5 = [(i , i =1 , 1000) ]
- 数组中所有元素均为同一值,可直接赋值,如:
REAL , DIMENSION(10)::array6 = 1.0 ! 所有元素均为1.0
-
用
READ
语句初始化;
3) 数组下标
N
个元素的数组通常用下标1,2······,N
来访问,即默认是从1开始,对应的声明形式如: REAL , DIMENSION(N)::array
。
此外,可以指定下标的取值范围,即在声明语句中声明下标的起始值和结束值,对应的形式如:REAL , DIMENSION(a:b)::array
,下标从a
开始,至b
结束,元素总个数为b-a+1
。
需注意的是,索引时下标不能超过定义的范围,否则可能中断,也可能返回一个非期望值(可能会访问至该数组相邻内存位置的其它数值)
4) 数组操作
-
整体数组
当两个数组的结构(行和列数)相同时,可用内置操作符(如+
)进行操作,此时两个数组的下标值不一定要相同。如:PROGRAM array_test IMPLICIT NONE REAL , DIMENSION(4) :: a = [1. , 2. , 3. , 4.] REAL , DIMENSION(-1:2) :: b = [5. , 6. , 7. , 8.] ! 下标不一致也不影响结果 REAL , DIMENSION(4) :: c c = a + b WRITE(*,*) c WRITE(*,*) -c ! 所有元素取反号 STOP END PROGRAM array_test
相应结果为:
6.000000 8.000000 10.00000 12.00000 -6.000000 -8.000000 -10.00000 -12.00000
-
部分数组
相当于是切片,具体语句为array(i:j:m)
,i
为起始下标,j
为结束下标,m
为增量,其中i
、j
和m
可以部分甚至全部缺省。具体例子如下:PROGRAM array_test IMPLICIT NONE REAL , DIMENSION(10) :: a INTEGER::count,i count = 1 DO i=1,20,2 a( count ) = i count = count + 1 END DO WRITE(*,100) a ! 结果很直观,不过多解释了 WRITE(*,100) a( : ) WRITE(*,100) a( 2 : 7 ) WRITE(*,100) a( 2 : ) WRITE(*,100) a( : 7 ) WRITE(*,100) a( : : 2) 100 FORMAT(*(F4.1,1X)) ! *号表示无限循环使用 STOP END PROGRAM array_test
相应结果为:
1.0 3.0 5.0 7.0 9.0 11.0 13.0 15.0 17.0 19.0 1.0 3.0 5.0 7.0 9.0 11.0 13.0 15.0 17.0 19.0 3.0 5.0 7.0 9.0 11.0 13.0 3.0 5.0 7.0 9.0 11.0 13.0 15.0 17.0 19.0 1.0 3.0 5.0 7.0 9.0 11.0 13.0 1.0 5.0 9.0 13.0 17.0
5) 数组输入和输出
-
逐个变量操作,如
REAL , DIMENSION(5) :: a WRITE(*,100) a(1) , a(2), a(3) , a(4) , a(5) ! 输出 READ(*,100) a(1) , a(2), a(3) , a(4) , a(5) ! 输入 100 FORMAT(5F4.1)
但当有多个数据时,操作麻烦。
-
隐式
DO
循环
隐式DO
循环作为控制变量的函数来多次输出/输入数组数据,语句为:WRITE(unit,format) (arg1,arg2,...,index = istart,iend,incr)
READ(unit,format) (arg1,arg2,...,index = istart,iend,incr)
可将上面例子写成:REAL , DIMENSION(5) :: a INTEGER::i WRITE(*,100) (a(i),i=1,5) READ(*,100) (a(i),i=1,5) 100 FORMAT(5F4.1)
另一个例子:
REAL , DIMENSION(5) :: a = (/1.,2.,3.,4.,5./) INTEGER::i WRITE(*,100) (a(i),2*a(i),3*a(i),i=1,5) ! 每个i有三个数,共有15个数 100 FORMAT(15F5.1)
相应结果为:
1.0 2.0 3.0 2.0 4.0 6.0 3.0 6.0 9.0 4.0 8.0 12.0 5.0 10.0 15.0
如果将输出格式改成
FORMAT(5F5.1)
,(具体原因见显式与隐式DO的区别)则输出结果为:1.0 2.0 3.0 2.0 4.0 6.0 3.0 6.0 9.0 4.0 8.0 12.0 5.0 10.0 15.0
-
嵌套的隐式
DO
循环
最里面的括号为内层,外面的为循环外层,如例子中的j
是内层循环,i
是外层循环:INTEGER::i , j WRITE(*,100) (( i , j , j = 1 , 3 ) , i =1 , 2) 100 FORMAT(I1,1X,I1)
相应结果为:
1 1 1 2 1 3 2 1 2 2 2 3
-
显式
DO
循环与隐式DO
循环的区别
以输出WRITE
语句为例:
①显式操作:PROGRAM DO1_test IMPLICIT NONE INTEGER , DIMENSION(5) :: a = (/1,2,3,4,5/) INTEGER:: i DO i=1,5 WRITE(*,100) a(i) , 2*a(i) , 3*a(i) 100 FORMAT(6I3) END DO STOP END PROGRAM DO1_test
②隐式操作:
PROGRAM DO1_test IMPLICIT NONE INTEGER , DIMENSION(5) :: a = (/1,2,3,4,5/) INTEGER:: i WRITE(*,100) (a(i) , 2*a(i) , 3*a(i) , i=1,5) 100 FORMAT(6I3) STOP END PROGRAM DO1_test
相应结果为:
①显式结果:1 2 3 2 4 6 3 6 9 4 8 12 5 10 15
②隐式结果:
1 2 3 2 4 6 3 6 9 4 8 12 5 10 15
区别:
对于显式循环,每一次循环会执行一条WIRTE
语句,共有五条WIRTE
语句,每一条WIRTE
语句上只有三个变量,因此每次只会使用格式描述符(6I3)
中的前三个,即实际格式为FORMAT(3I3)
;
对于隐式循环,尽管会执行五次,但是只有一条WIRTE
语句,变量个数大于格式数目,格式可以重复使用,因此每六个变量使用一轮格式,再进行换行。 -
整体和部分输出
同样,在I/O语句中允许切片操作array(i:j:m)
。具体不详述。