转自:http://icbc168.blog.163.com/blog/static/1270839842010962284499/
FORTRAN90小结
2010-10-06 14:28:44| 分类: 至诚课程 | 标签: |举报 |字号大中小 订阅
;fortran语言的发展:54年提出,56年开始使用——58年fortran二——62年fortran四——66年fortran66——78年fortran77——91年fortran90
;fortran77一行分为四个区的书写格式,在fortran90中不再采用该格式。
;一个简单的fortran90程序:
华氏温度与摄氏温度的换算公式,先输入某一华氏温度TH,计算出相应的摄氏温度TC。
PROGRAM H_TO_C !program后空一格写主程序名,其后程序空两格写
!Given the Fahrenheit temperature, to calculate the Centigrade !为注释行
REAL::TC,TH ::为双隔号,由两个:连成,后各变量间用逗号隔开
READ * , TH
TC=5*(TH-32)/9
PRINT * , TH,TC
END PROGRAM H_TO_C end program后空一格写本程序名,程序名也可不写
;输入M个整数,将其相加,打印出它们的和:
Program cal_m_sum
Implicit none !表示不使用隐式说明,即隐约规则,90程序中一般要有
Integer::n,m
Real::t,a
n=0;t=0 !将两个语句写在一行上,中间用分号;分隔
print * ,’input number of data:’
read * ,m
do !do—end do结构,不带循环变量的循环结构,exit表示跳出循环
read * ,a
t=t+a
n=n+1
if(n>=m)exit
end do
print * ,t
end program
;求4—8五个数阶乘之和:
Function factor(n) result(fac_result) !function,result皆为关键字,表示函数子程序和函数的结果
Implicit none
Integer::n,fac_result,i
Fac_result=1
Do i=1,n
Fac_result=fac_result*i
End do
End function factor
Program cal_factor
Implicit none
Integer::factor,s=0,I !90中变量在类型说明语句中可以赋值,如s=0
Do i=4,8
S=s+factor(i)
End do
Print * ,’s=’,s
End program
;90程序是一种分块形式的程序,由若干个单元块组成,各单元有相似的语句组织形式,其中主程序单元起整体控制作用。按现代编程要求,应尽量多使用子程序单元,有利于程序的维护。一般形式:
主程序单元 函数子程序单元
Program 主程序名 function 函数名(参数) result(结果变量)
程序体 程序体
End program 主程序名 end function 函数名
;real,dimension(1:10)::a,b !说明a,b都是具有10个元素的一维实型数组。
;注释,90提倡用!,不提倡用c或*。
;90中,大小写是等价的。
;字符型常量,又叫字符串,由一对单撇号’’或一对双撇号””间的字符序列组成。
;90中使用的名字,如程序名,变量,常量等,其组成成分可以是字母,数字和下划线,但第一个字符必须是字母,在名字中也不能出现空格。
;有些常用符号无法直接书写,可将其读音或英文名字写出,如theta,alpha,beta
;90不提倡77中的隐式说明,为抑制隐式说明发生作用,应在说明部分一开始就写语句:implicit none,以此向系统声明在本程序中,隐式说明不起作用。
;90中五种变量类型说明:整型integer,实型real,复型complex,逻辑型logical,字符型character。格式:关键字在前,待说明变量在后,中间用双分隔符::隔开,多个变量时,其间用,分隔。如 integer::I,j,k
;90中在变量说明部分有新功能:1,变量说明同时赋初值:integer::i=5,j=126
2,变量说明同时定属性:integer,parameter::i=5,j=24
Real,dimension(1:10)::a
;90中多了派生数据类型:根据需要而定义的新的数据类型,如每个学生可由系、班级、姓名、学号唯一确定,可将学生定义为含有系department,班class,姓名name,学号number四个分量组成的一个派生结构:
Type student
Character(len=20)::department
Character(len=10)::class
Character(len=15)::name
Integer::number
End type student
Student作为一个新的派生数据类型,可以来说明变量:若说明person具有student类型:
Type(student)::person
赋值:person=(“computer”,”92_2”,”Lilin”,21)
;数组类型说明:
Integer,dimension(3,2)::a
Real,dimension(2,2,2)::b
在90中,允许对数组名进行运算:如real,dimension(3,3)::a 3*a就相当于数组a中每个元素的值乘以3后所形成的新数组;sqrt(a)则相当于a中每个值取出都做平方根运算后形成的新数组。
在90中也允许对数组片段进行操作。
;变量类型说明语句integer::I,j,k 语句最后没有标点符号。
;对类型相同但形不同的实体,可方便的使用一句语句来说明:
Integer::a,b,x(10),y(3,3)
Real::m(2,4),n
;整型数运算速度快,在机内存储没有误差,但能表达的范围小,
;实型数能表示小数、分数及不同的精度,表达的值的范围大,但数的外部表示与机器存储会有误差,如送入一个实数10.2,在机内可能会表示为10.19999998。故在程序中,能用整数的地方尽量用整数,在使用实数的地方尽量避免作相等和不相等的比较,如语句:
If(a= =10.2) print * ,a 应改为 if(abs(a-10.2)<1.0e-6) print * ,a
;用语句 implicit none 来消除I-N规则。
;类型说明语句中可以给变量或部分变量赋初值,如real::x=1.2,y=2.5,z
;90中的种别:一个数据在内存中占有一定数目的存储单元,同一类型中数的大小和精度要求不同,它们要求的存储单元数量也不相同,按照变量表达的值的范围与精度,把同一类别划分为几个种别,不同种别分配不同数目的存储单元。Real(kind=2)::x 说明x是实型,种别参数是2,real::a,b 表示变量a,b的种别缺省,指采用系统规定的标准值。90中的内在函数有一部分是专用于种别选择的。
;内在函数:
基本函数:1 求三角函数时,自变量必须以弧度为单位,若为角度,需先转换。
2 函数对自变量的类型有要求:sin,log,exp,sqrt等要求自变量为实型,不能是整型。
3 自变量可以是常数、变量或表达式:sin(1.0),sin(a/3.0+0.5),sqrt(sqrt(625.0))
转换函数:int(x),real(x)
查询函数
;实型编辑符:Fw.d—浮点型,小数形式,w—总宽度,d—小数位数。如有实型数x=10.56,y=-2.7,语句print’(F10.3,F8.4)’,x,y的输出格式为:
10.560 -2.7000
数据不足w位用前置空格补全,小数位数少于d位用尾零补足。如小数位数超过d位,则第d+1位产生截断并四舍五入。如整个位数超过w位,则输出w个星号。应合理选择w,d.
;实型编辑符:Ew.d[Ee]—指数形式,w为字段宽度,d为小数部分中小数的位数,[Ee]为可选项。整个数是一个规格化后的小数后跟10的n次幂。如x=212.345,则语句
Print’(E12.3)’输出结果是
0.212E+03
而语句print’(E12.3E4)’输出结果是
0.212E+0003
如果不规定指数部分的位数,一般为4位:E占1列,正负符号占1列,指数占2列。
注意:w的值不应小于d+6,如果输出的是负数,则w大于等于d+7。
;输入数据按数学习惯书写,各数间用逗号或空格分隔。
;输入语句:1 基本格式输入:read(5,’(I7)’)x,y 当输入设备为系统隐含指定的设备时,有两种方法:
Read(*,’(I7)’)x,y 或 read’(I7)’,x,y
2 表控格式输入:read(5,*) 或 read(*,*) 或 read*,
;输出语句:1 基本形式(自定格式)write(6,’(2F6.2)’)x,y F前的2表示重复系数,表示在一行内输出2个实数。
当设备是系统隐含指定的,有两种简化方法:write(*,’(2F6.2)’)x,y 或
print’(2F6.2)’,x,y 注意中间又多了个,
2 表控格式输出 write(6,*)x,y 或 print*,x,y
注意:print语句的输出设备由计算机系统隐含指定,而write语句则可在希望的任何设备上输出,用途更广。
语句print* 和 write(*,*) 都表示输出一个空白行。
;字符型编辑:A,不关心长短,如要输出:there are 5 books.字样,共三项,字符串’there are’,整型变量I值,字符串’books’,print’(A,I2,A)’,’there are’,I,’books.’
;X编辑符:输出空格,避免两个相邻数据紧挨在一起,插入空格。一般形式nX,n为重复系数,print’(F3.1,5X,F3.1)’,X,Y
;/编辑符:下一行输出,print’(F3.1/F3.1)’,X,Y
;一个记录的编辑格式:由其需要的各种编辑符组合在一起,彼此用逗号隔开,用括号括起来,再在外面加上单撇号或双撇号作定界符,print’(F3.1,’’AND’’,F3.1)’,X,Y
;90中六种关系运算符:> ,<, = =,>=,<=,/=。77版本中的表示法不提倡使用了。
;逻辑常数:只有两个,.true.和.false.,
逻辑变量:logical,dimension(8)::L
Logical::L1=.true.,L2=.flase.
逻辑表达式:五个逻辑运算符:.and. .or. .not. .eqv. .neqv. (两边各有一点,不可少)
;IF语句分有名和无名两种,一般为无名,有名:如
First:if()then !中间用冒号分隔
End if first !之间空一格
;DO循环:1 不带循环变量的DO结构
Do
循环体
End do
或
Do
If()exit !exit—出口,控制循环,中止或跳出循环。Exit语句
End do
2 带循环变量的DO结构
Do i=1,100,2
S=s+i
End do
3 DO WHILE结构
Do while(i<7)
I=i+1
F=f*i
End do
;函数子程序
Function isum(n) result(isum_result)
Implicit none
Integer::n,isum_result,i
Isum_result=0
Do i=1,n
Isum_result=isum_result+i
End do
End function isum
;函数语句:function 函数名(虚参) result(结果名)
!多个虚参,彼此用逗号隔开,都要在说明语句中说明类型。若没有虚参,则为空括号。
!result后的变量名通常写成:函数名_结果 的形式,必须在说明语句中说明类型。
;子列子程序:
Subroutine isum(n,isum_value)
Implicit none
Integer,intent(out)::isum_result !属性说明:intent
Integer,intent(in)::n
Integer::i
Isum_result=0
Do i=1,n
Isum_result=isum_result+i
End do
End subroutine isum
Program exam_sub
Implicit none
Integer::isum_x,x
Read * ,x
Call isum(x,isum_x)
Print * ,’sum=’,isum_x
End program exam_sub
;虚实结合的原则:实元和虚元个数相等,相应位置上的类型一致。也可灵活:
1 关键字变元
Subroutine sum(m,sum_value1,sum_value2)
Call sum(m=n,sum_value2=sumy,sum_value1=sumx)
注意:主调程序如采用关键字变元调用过程,就必须写出被调子程序的接口块。
Subroutine hf(a,b,m,n)
Integer,intent(in)::a,b,m,n
Print * ,a*b+m*n
End subroutine hf
主调程序必须写出该子程序的接口块:
Interface !接口块内容为被调用子程序说明部分的拷贝,用于通知编译程序主程序调用
Subroutine hf(a,b,m,n) !时所需要的接口信息,一般写在主调程序的类型说明语句之前。
Integer,intent(in)::a,b,m,n
End subroutine hf
End interface
2 可选择变元
90中子程序虚元中可有可选择项。在调用时可根据实际需要,只对部分虚元作虚实结合。
可选择变元要有optional属性,同时需要使用present函数。Present(x)函数用来检查变元x是否在程序执行部分出现。
Function ss(r,h) result(ss_result)
Implicit none
Real,intent(in)::r
Real,optional,intent(in)::h
Real::ss_result
Real::temp_h
If(present(h)) then
Temp_h=h
Else
Temp_h=1.0
End if
Ss_result=3.1415926*r**2*temp_h
End function ss
3 通过接口块更改虚元名称
90允许改变变元名称,在接口块中进行,故主调程序要改变虚元名称必须写出接口块。
;子程序的嵌套调用:
;模块:实现数据共享,起两个作用:共享与复制。
如:编程读入三个实数,调用函数aver3求平均值,调用函数max3求最大值:
法1:通过虚实结合传递数据 法2:用模块来实现数据共享
Function aver3(a,b,c) result(aver_value)各程序单元在说明部分都有这样两个语句:蓝色部分
Implicit none module exam_module
Real::a,b,c implicit none
Real::aver_value real::a,b,c
Aver_value=(a+b+c)/3.0 end module exam_module
End function aver3 Function aver3() result(aver_value)
Function max3(a,b,c) result(max_value) use exam_module
Implicit none Real::aver_value
Real::a,b,c Aver_value=(a+b+c)/3.0
Real::max_value End function aver3
Max_value=a Function max3() result(max_value)
If(b>max_value) max_value=b use exam_module
If(c>max_value) max_value=c real::max_value
End function max3 Max_value=a
Program aver_max_1 If(b>max_value) max_value=b
Implicit none If(c>max_value) max_value=c
Real::a,b,c End function max3
Real::aver3,max3 Program aver_max_2
Read * ,a,b,c use exam_module
Print * ,aver3(a,b,c),max3(a,b,c) Real::aver3,max3
End program aver_max_1 Read * ,a,b,c
Print * ,aver3(),max3()
End program aver_max_2
注意:一个程序中可有多个模块程序单元,每个模块都要独立编写。
各程序单元通过use exam_module是变量a,b,c成为共享数据。在主程序中输入3个数放入a,b,c后,函数aver3,max3中的a,b,c也具有了同样的值。故不必再把a,b,c作为变元,是aver3,max3成为无参数函数。当某个单元中改变了共享变量的值,其他程序单元中相应的共享变量的值也发生同样变化。
;递归:90新加的功能,调用自己,即递推和回归。
1 递归函数: 如用递归方法求n的阶乘
Recursive function fac(n) result(fac_result)
Integer,intent(in)::n
Integer::fac_result
If(n= =o)then
Fac_result=1
Else
Fac_result=n*fac(n-1)
End if
End function fac !先从上而下一层层递推,再反向一层层回归,最后求得函数fac(n)的值。
Program recursive_fun !调用递归函数的主程序最好写出递归函数接口块。
Implicit none
Interface
Recursive function fac(n) result(fac_result)
Integer,intent(in)::n
Integer::fac_result
End function fac
End interface
Integer::n
Read * ,n
Print * ,fac(n)
End program recursive_fun
2 递归子列子程序
;外部过程与内部过程
外部过程:未包含在主程序中
内部过程:如以内部过程a和fa为例:
Program main
(主程序说明部分)
(主程序执行部分)
Contains
Subroutine a
(子程序a说明部分)
(子程序a执行部分)
End subroutine a
Function fa() result(fa_result)
(函数fa说明部分)
(函数fa执行部分)
End function fa
End program
如:编程,求两个数之和。
法1:用外部过程实现
Program external_proc
Implicit none
Integer::a,b,sum
Read * ,a,b
Call add(a,b,sum)
Print * ,’sum=’,sum
End program external_proc
Subroutine add(a,b,sum)
Implicit none
Integer,intent(in)::a,b
Integer,intent(out)::sum
Sum=a+b
End subroutine add
!虽实参和虚参同名,但它们之间并不能直接传递数据,必须通过虚实结合实现。
法2:用内部过程实现
Program internal_proc
Implicit none
Integer::a,b,sum
Read * ,a,b
Call add
Print * ,’sum=’,sum
Contains
Subroutine add
Sum=a+b
End subroutine add
End program internal_proc
!点评:子程序中并无变量说明,也没有虚参,主程序调用时只写子程序名,因变量a,b,sum在主程序中说明后便作为全局变量,子程序可直接引用这些变量,其结果自动带回主程序。
!内部过程的两个主要特征:1 没有说明语句,所使用的变量等的说明统一放在主程序说明部分;2 没有虚参,调用时只需写一个过程名。
;数组:
;数组构成器(/ /):对数组赋值。如a=(/(sqrt(real(i)),i=1,4)/) 隐含do循环数组构成器,sqrt函数的自变量必须是实型的,但此处i是整型,故取自变量为real(i)。
;90规定,引用一个数组或其元素有三种形式:
1 数组名:代表所有元素
2 数组元素:代表一个元素
3 数组片段:代表若干个元素
数组片段有两种表示方法:1 连续片段法:a(3:6) 2 下标三元组法:可把不连续的元素组成数组片段,数组名(a:b:c),下标,上标,步长。可略写:如integer,dimension(6:50)::a a(10:30:1),a(:20:5),a(8::10)
;90中数组形式有4种:
1 常数组:过去所涉及的数组都是常数组,使用范围广。如real,dimension(2:5+7)::a
2 可调数组:维界表达式为整型变量,如real,dimension(n:m)::c 说明数组C是可调数组,n,m为可调维。只可在子程序中作虚数组用,数组名和可调维必须列入子程序的虚参中,如
Subroutine sub(c,m,n)
Real,dimension(n:m)::c
可调维在子程序中没有确定的值,需由主程序调用时通过虚实结合赋予确定的值。如
Call sub(a,10,20) 这样,虚数组c就与实数组a虚实结合,形状为(10:20)
3 假定形状数组:不出现上下维界,用一个冒号:表示,如
Real,dimension(:)::d1 一维实型 假定形状 数组
Integer,dimension(:,:)::d2 二维整型 假定形状 数组
只能在子程序中作虚数组用。或只写出维的一个边界,如real,dimension(3:)::d3
4 动态数组:其维界可在程序执行过程中按需变化,即数组占据的存储空间可按需分配。如
Real,dimension(:),allocatable::al1,al2
! allocatable为属性,表示该数组是可分配存储空间的动态数组,al1,al2都是一维实型动态数组。
用allocate语句分配内存:
Allocate(al1(m),al2(6:n)) ! 给数组al1分配m个单元,形状是(1:m)
用deallocate语句释放内存:如某动态数组的任务完成,可释放,将内存还给系统。
Deallocate(al1,al2)
释放后,数组形状不再存在,即不能再使用该数组,元素,片段。
释放不再使用的动态数组的内存空间是良好的程序设计习惯,有利于提高内存的利用率。
;二维数组:按列存储。输入语句
Read * ,a 与输入语句
Read * ,((a(i,j),i=1,3),j=1,3) 是等价的。如果想按行输入数据,则
Read * ,((a(i,j),j=1,3),i=1,3)
;90提供了强大的数组运算功能,允许把整个数组作为一个操作数运算,也允许在赋值语句中对整个数组或片段赋值,就如同对一个简单变量的赋值一样。如a=0,b=a-5 a,b为数组。
;数组内在函数:90提供了丰富的数组操作函数,
1 求数组大小的函数:size(a) 即求数组a元素的个数。
2 求数组极值等的函数:最大值元素:maxval 最小值元素:minval 最大值元素下标(位置):maxloc 最小值元素下标:minloc
Maxloc(a)的返回值:为最大值元素下标组成的数组构成器,如若maxloc(a)的值为(/3,2/) 即
最大值的元素在第3行第2列。又如数组D:
Integer,dimension(-5:1),parameter::d(/1,0,-12,-2,16,-1,8/)
D的最大值16,下标-1,由于maxloc是与位置有关的函数,它返回系统是将数组按维界下界为1重新排列后的下标,故maxloc(d)的函数值是(/5/)而不是(/-1/)
3 求数组各元素之和的函数sum和各元素之积的函数product
函数sum的一般形式:sum(array,dim,mask)其中:array是被求和的数组名,必选项。Dim和mask可选,mask屏蔽作用,其值为逻辑表达式,满足条件的元素求其函数值,不满足条件的被屏蔽在外,不参加运算。若只想求正元素值之和,则sum(a,mask=a>0)。Dim指明哪一维来求函数值。取值范围为1到最大维数。Sum(b,dim=1)按列求和,值为一个(几列的)向量。Sum(b,dim=2)按行求和,值为一个(几行的)向量。即向量的元素个数为数组的行数。
Sum(b,mask=b>0,dim=1)表示按列求正元素之和。没有满足条件的元素时,其和为0.
Product(array,dim,mask)同上。没有满足条件的元素时,乘积为1.
4 求维的下界的函数Lbound和上界的函数ubound
Lbound(array,dim)
5 数组转置函数transpose
Transpose(matrix),要求数组matrix维数为2,即矩阵。
;屏蔽数组赋值:where语句或where结构,似标量操作时的if语句和if结构。一般形式:
Where(数组关系表达式)数组赋值语句
注:数组关系表达式:以数组名为操作对象。所有这种赋值操作,都是对每个对应位置上的元素的操作。A,b皆为数组,形状相同:
Where(a<0)b=0 :系统逐一检查数组a各元素值,若某一位置上元素小于0,则b对应位置上的元素置0,其他元素不变。相当于do结构:(假定a,b一维数组,下标从1开始)
Do i=1,size(a)
If(a(i)<0)b(i)=0
End do
又如:
Where(c= =0)
C=1
Else where
A=b/c
D=b*c
End where
;if结构只能用于标量运算,
Where结构只能用于数组操作。
;字符型数据:
1 字符型常量:括在一对单撇号’’或一对双撇号””之间的一串字符。
2 字符型变量:character(len=15,kind=2)::a,c
当只有长度说明无种别参数说明时,character(len=15)::a与character*15::a等价。
字符连接符:’//’
;派生类型
;指针结构
;数据文件:先把输入数据形成一个数据文件,存放于外部介质,程序从这些文件上读入数据,计算后得到的输出结果也存放到数据文件中。
文件是记录的序列。FORTRAN程序,又称源程序,由若干行组成,需要存放到文件中才能编译、连接和运行。存放源程序的文件称为源程序文件,而存放程序运行时所需要的输入数据和输出数据的文件成为数据文件。
按存取方式,文件可分为顺序存取文件和直接存取文件。按文件记录的格式编辑,分为有格式文件和无格式文件。内存中数据是采用二进制内码形式存放的,如果外存中的数据也采用二进制内码方式存放,读写操作时不需要进行格式编辑,需使用无格式文件。否则,内外存之间的数据传递要按所给的格式进行编辑,是有格式文件。
重点讨论有格式的磁盘数据文件的顺序和直接存取方法:
Open(3,file=’data.dat’,status=’unknown’)
Read(10,fmt=’(2F5.1)’)x,y
;顺序文件的存取:
Rewind语句:
Backspace语句:
End file语句:
;直接文件的存取: