FORTRAN是英文“FORmula TRANslator”的缩写,译为“公式翻译器”,它是世界上最早出现的计算机高级程序设计语言,广泛应用于科学和工程计算领域。FORTRAN语言以其特有的功能在数值、科学和工程计算领域发挥着重要作用。
早在1951年,美国IBM公司约翰·贝克斯(John Backus)针对汇编语言的缺点着手研究开发FORTRAN语言,并于1954年在纽约正式对外发布。称约翰·贝克斯提出的FORTRAN语言为FORTRANⅠ,FORTRANⅠ虽然功能简单,但它的开创性工作,在社会上引起了极大的反响。到1957年第一个FORTRAN编译器在IBM704计算机上实现,并首次成功运行了FORTRAN程序。
在1958年,对FORTRANⅠ进行了扩充和完善,引进了子函数等概念,推出了商业化的FORTRANⅡ版本。之后,FORTRAN语言发展迅速,多种版本相继在其它计算机上实现。
符:Fortran不区分大小写
Fortran 格式:自由格式和固定格式。Fortran程序代码扩展名为:*.For 或*.F的文件就是指固定格式;以*.F90为扩展名的文件,就是自由格式。
à固定格式:规定了程序代码每一行中每个字段的意义。第7~72个字符,是可以用来编写程序的字段。每一行的前5个字符只能是空格或数字,数字用来作为“行代码”。每一行的第6个字符只能是空格或“0”以外的字符。
第1个字符 |
如果是C、c或者星号*,这行文本会被当成说明批注,不会被编译 |
第1~5个字符 |
如果是数字,就是用来给这一行程序代码取个代号。不然只能是空格 |
第6个字符 |
如果是“0”以外的任何字符,表示这一行程序会接续上一行 |
第7~72个字符 |
Fortran程序代码的编写区域 |
第73个字符之后 |
不使用,超过的部分会被忽略,有的编译器会发出错误信息 |
à自由格式:叹号(!)后面的文本都是注释。 每行可以编写132个字符。行号放在每行程序的最前面。 一行程序代码的最后如果是符号&,代表下一行程序会和这一行连接;如果一行程序代码的开头是符号&,代表它会和上一行程序连接。
Fortran的数据类型
à整型(Integer) à浮点数(Real) à复数(Complex) à字符(Character)
à逻辑判断(Logical)—True or False
Remark: Visual Fortran安装好后,默认的安装目录C:Program FilesMicrosoft Visual StudioDV98in下有一个Bitviewer程序可以用来表看各种数据格式实际在内存中的二进制数据。
Fortran的数学表达式
()(括号)、**(乘幂)、*(乘法)or /(除法)、+(加法) or –(减法)à优先级(高à低).
输入(Write)输出(Print)命令
Fortran程序通常以Program描述来开头,Program后面还要接一个自定义的程序名称(这个名称可以完全自定义,不需要和文件名有任何关系)。Fortran程序最后还要有End描述,表示程序代码写到这一行结束。
Write(*,*)命令:括号中的两个星号都有各自的意义,第一个星号代表输出的位置使用默认值,也就是屏幕,第二个星号则代表不特别设置输出格式。
终归一句话,Write这个命令的最简单用法,就是在括号中挂上两个星号,再把所要输出的字符串用两个双引号引起来放在后面。
E.g.:write (*,*) “Hello, Acuzio!” à 完整的写法 write(Unit = *, FMT=*) “Hello, Acuzio!”
Write命令注意:
l 每一次执行Write命令后,会自动切换到下一行来准备做下一次的输入
l 因为双引号是用来“输出”字符串的,所以想要输出双引号时,要连用两个双引号。
l Fortran90可以使用双引号或单引号来封装字符串,Fortran77标准中只能使用单引号,不过大部分的Fortran77编译器还是可以接受双引号。
STOP命令:是终止程序的意思,它可以出现在程序的任何地方,程序执行到这个命令就会中止。除非必要,不要把Stop命令使用在主程序结束之外的其他地方。因为一个程序,如果有太多的终止点会容易出错。
把上面例子中用Print命令,程序执行的结果是一样的àPrint *, ”Hello, Acuzio!”
Print的用法和write大致上相同,只是print后面不使用括号,而且只有一个星号。这个星号的意义是不限定输出格式。Print和Write的不同处就在于少了Write的第一个星号,也就是少了赋值输出位置的能力,Print命令只能针对屏幕来使用。建议尽量使用Write来做输出的工作,因为如果日后想把程序的输出转换到其他地方,例如转换到文件中,使用Write命令的程序改写起来比较容易,只有把UNIT值指到另一个输出位置就行了。
Integer:Integer(kind = 4) a Integer *4 a Integer(4) a
其中kind=4、*4、(4)都是赋值要使用4个bytes来存放整数的意思。
声明变量的原则:
l 变量的名称以使用英文字母为原则,可以内含下划线或数字,但前缀必须是英文字母
l 变量名字的长度,在77标准中最起码支持6个字符长,90标准中最起码支持31个字符长。也就是说在Fortran77中变量长度最后是在1~6之间,在Fortran90中变量长度则最后是在1~31之间
l 变量名称最好不要和Fortran的执行命令同名,也不能和主程序的名称或是前面声明过的变量同名。
l 程序中辨认变量时,不会区分它的大小写
Fortran90的声明语法多了一些变化,它可以在类型的后面先写两个冒号“::”,再写上变量的名称
Real:
Real(kind=4)表示单精度。Real(kind=8)表示双精度
Complex:
Fortran中声明复数的方法:Complex a
复数是有实部和虚部两个部分组成,而Fortran中保存这两个数字的方法是用两个浮点数来保存,所有复数也可以分成单精度及双精度两种类型。
要设置一个复数数值的方法如下:a=(x,y) !x为实部,y为虚部,当a=(3.2,2.5)时,表示a=3.2+2.5i
Character:
声明:character(len=10) a character(10)a character*10 a character*(10) a
字符串长度需要多少字符,就赋值多少数字给它
Program ex Character(len=20) string String = “Good morning.” Write(*,*) string String(6) = “evening.” !重新设置从第六个字符之后的字符串 Write(*,*) string end |
上例中 string(1:2) = “GO” !字符串最前面两个字符会变成GO
String(13:13)=”!” !字符串的第13个字符会变成叹号
用(//)可以把前后两个字符串连接起来
Fortran有关字符串运行的函数
Char(num) |
返回计算机所使用的字符表上,数值num所代表的字符 |
IChar(char) |
返回所输入的char字符在计算机所使用的字符表中所代表的编号,返回值是整数类型 |
Len(string) |
返回输入字符串的声明长度,返回值是整数类型 |
Len_Trim(String) |
返回字符串去除尾端空格后的实际内容长度 |
Index(string,key) |
所输入的String和key都是字符串。这个函数会返回key这个“子字符串”在“母字符串”String中第一次出现的位置 |
Trim(string) |
返回把string字符串尾端多余空格清除过后的字符串 |
Logical:
逻辑变量并赋值。Logical a = .true.
设置逻辑变量的方法:当设置“真”值或者“假”值,请注意要在true和false的前后要加上两个点
输入命令Read
Read(*,*) read命令在使用时和write一样,都有两个星号。代表的意义也是差不多的,第一个星号代表输入的来源使用默认的设备(也就是键盘),第二个星号代表不指定输入格式
格式化输入输出(Format)
Program ex Integer a a = 100 write(*,100) a !使用行代码100,也就是第五行的格式来输出变量a 100 format(I4) !最前面的100是行代码,把这一行程序代码给一个编号 End |
Format格式
Aw |
以w个字符宽来输出字符串 |
BN |
定义文本框中的空位为没有东西,在输入时才需要使用 |
BZ |
定义文本框中的空位代表0,在输入时才需要使用 |
Dw.d |
以w个字符宽来输出指数类型的浮点数,小数部分占d个字符宽 |
Ew.d[Ee] |
以w个字符宽来输出指数类型的浮点数,小数部分占d个字符宽,指数部分占e个字符 |
ENw.d[Ee] |
以指数类型来输出浮点数 |
ESw.d[Ee] |
以指数类型来输出浮点数 |
Fw.d |
以w个字符宽来输出浮点数,小数部分占d个字符宽 |
Gw.d[Ee] |
以w个字符宽来输出整数,最少输出m个数字 |
Iw[.m] |
以w个字符宽来输出整数,最少输出m个数字 |
Lw |
以w个字符宽来输出T或F的真假值 |
nX |
把输出的位置向右跳过n个位置 |
/ |
代表换行 |
: |
在没有更多数据时结束输出 |
kP |
K值控制输入输出的SCALE |
Tn |
输出的位置移动到本行第n列 |
TLn |
输出的位置向左相对移动n列 |
TRn |
输出的位置向右相对移动n列 |
SP |
在数值为正时加上“正号” |
SS |
取消SP |
Fortran 90添加的格式 |
|
Bw[.m] |
把整数转换成二进制来输出、输出会占w个字符宽,固定输出m个数字。m值可以不给定 |
Ow[.m] |
把整数转换成八进制来输出,输出会占w个字符宽,固定输出m个数字。m值可以不给定 |
Zw[.m] |
把整数转换成十六进制来输出,输出会占w个字符宽,固定输出m个数字。m值可以不给定 |
变量名称的取名策略:变量的名字中可以使用的字符集包括英文的26个字母、0~9这10个数字以及下划线“_”,不过前缀必须是英文字母。变量名称的长度限制随着各家编译器的不同而不同,Fortran 标准规定最少要支持到6个字符,Fortran90则最少要支持到31个字符
Implicit
Fortran 标准中有一项不太好的功能,它的变量不一定要经过程序声明才能使用,编译器会根据变量的第一个字母来自东决定这个变量的类型。第一个字母为I、J、K、L、M、N的变量会被视为整数类型,其他的变量则会被当成浮点数来使用。
Implicit命令的功能是用来设置“默认类型”。所谓的默认类型,是指Fortran不经过声明,由第一个字母来决定变量类型。可以经过Implicit描述来决定哪些字母开头的变量会自动使用某种类型
Implicit integer (A,B,C) !A、B、C开头的都被视为整型数 Implicit integer(A-F,I,K) !A到F及I、K开头的变量都视为整型数 Implicit real(M-P) !M到P开头的变量都视为浮点数 Implicit none !关闭默认类型功能,所有变量都要事先声明 |
常数的声明方法(Parameter)
Program ex Implicit none Real ::pi Parameter(pi = 3.14129) Write(*,”(F4.2)”) sin(pi/6) end |
在Fortran90里,Parameter可以作为形容词,和变量的声明同时写在一起
Real, parameter ::pi=3.14159 !这里pi前面的冒号不能省,和上面代码不同(上面的可以省略)
设置变量的初值
变量内容并不一定要在程序执行时才设置,可以在声明时同时给予初值。在Fortran90偶那个,在设置变量初值时,直接把数值写在声明的变量后面就行了。使用这个方法来设置初值是,不能省略声明中间的那两个冒号(Fortran90)
在fortran77中则要使用Data命令设置初值
Fortran 90 |
Fortran 77 |
program ex90 implicit none integer ::a=1 real ::b=2.0 complex ::c=(1.0,2.0) character (len=20) ::str="Hello Acuzio!" write (*,*) a,b,c,str end |
program ex77 implicit none integer a real b complex c character (len=20) str data a,b,c,str/1,2.0,(1.0,2.0),’Hello ‘/ write (*,*) a,b,c,str end |
等价声明(equivalence)
把两个以上的变量,声明它们使用同一个内存地址,就是“等价声明”。使用同一个内存位置的变量,只要改变其中一个变量,就会同时改变其他变量的数值
Integer a,b Equivalence(a,b) |
Fortran 90 的自定义数据类型
使用关键字:type
Type ::person Character(len=30) ::name Integer ::age Integer ::length Integer ::weight End type person |
Type(person) ::a !声明一个person类型的变量 a%name !引用person中的name |
Kind的使用
Kind描述如果搭配上一些Fortran90的库函数,可以增加程序代码的“跨平台”能力
Fortran 90提供库函数来判断所要记录的数值值域范围所需要的kind值
Selected_int_kind(n) : 返回如果想要记录n位整数时,所应声明的kind.返回-1时,表示无法提供所想要的值域范围
Selected_real_kind(n,e) : 返回如果想要能够记录具有N位有效位数、指数达到e位的浮点数所需要的kind值。返回-1表示无法满足所要求的有效位数、返回-2表示无法满足所要求的指数范围、返回-3表示两者都无法满足
IF基本用法
If(逻辑判断式) then …… End if |
If(逻辑判断式) then …… Else …… End if |
逻辑运算符:
Fortran 90 |
|
Fortran 77 |
||
== |
判断是否“相等” |
|
.eq. |
判断是否“等于” |
/= |
判断是否“不相等” |
|
.ne. |
判断是否“不等于” |
> |
判断是否“大于” |
|
.gt. |
判断是否“大于” |
>= |
判断是否“大于或等于” |
|
.ge. |
判断是否“大于或等于” |
< |
判断是否“小于” |
|
.lt. |
判断是否“小于” |
<= |
判断是否“小于或等于” |
|
.le. |
判断是否“小于或等于” |
逻辑判断式
.and. |
交集,如果两边的表达式都成立,整个表达式就成立 |
.or. |
并集,两边的表达式只要有一个成立,整个表达式就成立 |
.not. |
逻辑反向,如果后面的表达式不成立,整个表达式就成立 |
.eqv. |
两边表达式的逻辑运算结果相同时,整个表达式就成立 |
.neqv. |
两边表达式的逻辑运算结果不同时,整个表达式就成立 |
多重判断
If(条件1) then …… Else if(条件2) then Else …… End if |
浮点数及字符的逻辑运算
使用浮点数来做逻辑运算时,要避免使用“等于”的判断。因为使用浮点数做计算时,有效位数是有限的,难免会出现计算上的误差,理想中的等号不一定会成立。要使用浮点数来做“等于”的逻辑判断时,最好用其他方法来取代(ABS这个函数是取绝对值。使用误差小于某一个值来进行判断)
Select case语句
Select case(变量) Case(数值) …… Case(数值2) …… Case default …… End select |
在case里的冒号前后放两个数值时,代表在这两个数值范围中的所有数值
Remark:
l Select case只能使用整数(integer)、字符(character)及逻辑变量(logical),不能使用浮点数及复数
l 每个case中所使用的数值必须是固定的常量,不能使用变量
Pause, continue, stop
Pause的功能就跟它的字母意义相同,程序执行到pause时,会暂停执行,直到用户按下enter键才会继续执行。
Continue 无实际用途
Stop 结束程序执行
Fortran 90的库中,IAND用来做二进制的AND计算,IOR用来做二进制的OR计算
DO循环
Integer, parameter ::index = 1 Integer, parameter ::counts = 100 Do index,counts,1 …… End do |
Real,parameter ::weight =45.0 !答案 Real,parameter ::e=0.001 !误差 Real ::guess Do while(abs(guess-weight)>e) Write(*,*) “Weight” Read(*,*) guess End do |
循环控制:
Cycle和exit
Cycle 命令可以略过循环的程序模块中,在cycle命令后面的所有程序代码,直接跳回循环的开头来进行下一次循环
Exit 功能:可以直接“跳出”一个正在运行的循环
署名循环
循环还可以取“名字”,这个用途是可以在编写循环是能明白地直到End do这个描述的位置是否正确,尤其是在多层循环当中。署名的循环也可以配合Cycle、exit来使用。
数组(Array)
数组的声明方法:Datatype name(size)
赋初值:
integer A(5) Data a /1,2,3,4,5/ |
Integer a(5) Data a /5*3/ !5个3 |
Integer A(5) Integer i Data(A(i),i=2,4) /2,3,4/ !这是一个隐含式循环,I会从2增加到4,依照顺序到后面取数字。初值设定结果为A(2)=2、A(3)=3、A(4)=4,A(1)和A(5)没有设定 |
Fortran 90隐含式循环的功能可以更强大
Integer ::a(5)=(/(I,I=1,5)/) !设置结果:a(1)=1,a(2)=2,a(3)=3,a(4)=4,a(5)=5
Where
Where是Fortran95添加的功能,它也是用来取出部分数组内容进行设置
Forall
Forall是fortran95添加的功能。间断地说,它也可以看出是一种使用隐含循环来使用数组的方法,不过它的功能可以做得更强大。
Integer i Integer ::a(5) Forall(i=1:5) A(1)=5 End forall |
Forall详细语法为
Forall(triplet1[,triplet2[,triplet3……]],mask)
……
End forall
其中mask用来做条件判断
Fortran90 可以声明可变大小数组
Integer,allocatable ::a(:) !声明一个可变大小的一位数组 Integer ::students Read(*,*) students Allocate(a(students)) !配置内存空间 |
计算机的内存是有限的,当然也就不能无限制地去要求空间来使用。所以allocate命令在内存满载是,有可能会要求不到使用空间。Allocate命令中可以加上stat的文本框得知内存配置是否成功
Allocate(a(100),stat=err) !err是事先声明号的整型变量,做allocate这个动作时会经有stat这个叙述传给err一个数值,如果err等于0则表示allocate数组成功,而如果err不等于0
则表示allocate数组失败
Deallocate(a) 表示删除分配的内存
跟allocate相关的函数还有allocated,它用来检查一个可变大小的矩阵是否已经配置内存使用,他会返回一个逻辑值
If(.not. allocated(a))then Allocate(a(5)) End if |
函数
子程序(subroutine)的使用
子程序代码以subroutine开头,它同样要取一个名字,以end或end subroutine来结束。严格地讲,end subroutine后还可以再接上这个子程序的名字
program ex implicit none integer ::a=1 integer ::b=2 call add(a,b) end
subroutine add(first,second) implicit none integer ::first,second write(*,*) first+second return end |
函数的调用
program ex implicit none real ::a=5,b=4 real,external ::add !声明add是函数而不是变量 !调用函数add,调用函数不必使用call命令 write(*,*) add(a,b) end
function add(a,b) implicit none real ::a,b real ::add add =a+b return end |
全局变量
Common是fortran77使用“全局变量”的方法,它用来定义一块共享的内存空间
program ex implicit none integer ::a,b common a,b !定义a,b是全局变量中的第1及第2个变量 a=1 b=2 call showCommon() end
subroutine showCommon() implicit none integer ::num1,num2 common num1,num2 !定义num1,num2是全局变量中的第1及第2个变量 write(*,*) num1,num2 return end |
Block data
关于common还有最后要介绍的就是设置初值的方法,common变量不能直接在子程序或主程序中使用data来设置初值,要在block data程序模块中使用data命令来设置初值
program ex implicit none integer ::a,b common a,b !a,b放在不署名的全局变量空间中 integer ::c,d common /group1/c,d !c,d放在group1的全局变量空间中 integer ::e,f common /group2/e,f !e,f放在group2的全局变量空间中
write (*,"(6I4)") a,b,c,d,e,f end
block data implicit none integer a,b common a,b !a,b放在不署名的全局变量空间中 data a,b /1,2/ !设置a,b的初值 integer c,d common /group1/c,d !c,d放在group1的全局变量空间中 data c,d /3,4/ !设置c,d的初值 integer e,f common /group2/e,f !e,f放在group2的全局变量空间中 data e,f /5,6/ !设置e,f的初值 end block data |
变量的生命周期
在声明中加入save 可以拯救这些变量、增加变量的生命周期、保留住所保存的数据。这些变量可以在程序执行中永久记忆住上一次函数调用时所被设置的数值
program ex implicit none call sub() call sub() call sub() end
subroutine sub() implicit none integer ::count = 1 save count !赋值count变量会永远活着,不会忘记它的内容 write(*,*) count count = count + 1 return end |
在Fortran 90 中,可以把save跟声明写作同一行
Integer ,save ::count=1
传递函数
传递参数时,除了传递数字、字符等等数据之外,还可以把一个函数名称当成参数传送出去
program ex implicit none real,external ::func !声明func是个自定义函数 real,intrinsic ::sin !声明sin是库函数
call ExecFunc(func) !输入自定义函数func call ExecFunc(sin) !输入库函数sin end
subroutine ExecFunc(f) implicit none real,external ::f !声明参数f是个函数 write(*,*) f(1.0) !执行输入函数f return end
real function func(num) implicit none real ::num func = num*2 return end |
关键字Intrinsic表明所声明的sin是fortran的库存函数,而不是一个变量