2006-8-6 相信大家都对C语言有一定的了解,其实Fortran跟C相差不是很多。 我把自己认为比较合理快速学习Fortran的方法说下。 学习Fortran,会遇到Fortran77&Fortran90等等,两者差别不大,建议学习Fortran90或更 高,更加自由些(仅对一般用而言,其他优势可能体现不出来),对自己以后学习他 的程序包也会有好处。 大家一般只是为了编程为了计算而学Fortran,而不是为了学习Fortran而学Fortran,所以 我的建议是学习Fortran不要像学C那样拿一本很详细的教材从头至尾学下来,一个大家都 有不错的C语言基础,而且也没有太多的精力去专门研究这些,倒不如看些简易的教材(我 会附上),掌握基本语句之后直接从看最简单的程序开始。这样,很快就会体会到Fortra n的格式,可以开始自己写程序了。学习的顺序我建议如下: 1、 编一些仅含输入输出的程序,然后可以尝试把输入输出同文件结合起来(从文件里读 数据、写数据); 2、 然后可以学条件判断、循环语句,通过几个实例也可以很快掌握; 3、 再往后就是写子程序,就是程序的调用,相信那个时候,看了我的第一个例子(PROG RAM A)就应该能写出简单的含函数调用的程序,到了这里,基本上可以算告一段落,可以 进行结构上复杂的程序的编写; 4、 最后,可以学一下多个程序的编译甚至是多种语言程序的混编(如既有C又有Fortran 的多个程序一起编译)。多个程序的编译我不并不熟悉,就留给siriusbobo同志来解说吧 :-) 在编程中遇到困难然后再去查找资料和用法不失为一种好的方法,不必刻意去求学全。 当然,有足够时间和精力的同学强烈建议好好看教材,不必急于求成,有一个好的基础总 是一件很好的事。 Fortran相比C的优势的话在于它丰富的资源,C的优势可能是更加简洁,编译效率更高。但 对于我的平时使用来说,这两者的优势、劣势都体现不出来,自己的感觉是Fortran更接近 平时的科学语言,比较严谨些,更容易读懂不出错,比较符合习惯,变量、函数的声明上 也比C更方便灵活,以外函数的使用为例: ****************************************************************************** PROGRAM A real z read *,z call f(z) y=z print *,y end subroutine f(x) x=x**2 return end ****************************************************************************** 只需要加一个"subroutine"程序段,主函数即可用"call"调用,当然也可以写多个子程序 ,其中一个子程序也可以通过"call"来调用其他子程序。 就一般学习而言,除了子程序的编写,另外一个用得比较多的是文件的读写操作,读用 "read",写用"write",如下: ****************************************************************************** PROGRAM B real x open (1,file='in.dat',status='unknown') open (2,file='out.dat',status='unknown') read (1,100) x 100 format (1e12.7) close(1) write (2,200) x 200 format (1e15.8) close(2) end ****************************************************************************** 如果用"*"的话,就为默认形式,更具体的可以查看帮助或有关资料,比较好的方法是随时 做一个test程序,用来检测所学或所想。 对于上程序,出现的"100","200"是语句标号,这些标号为方便语句的跳转而出现,可以实 现循环、条件控制等,但也为了使程序结构化而不推荐使用,用goto语句和语句标号实现 语句的跳转如下: ****************************************************************************** PROGRAM C integer n real z n=0 read *,z 1 call f(z) y=z n=n+1 if (n<10) goto 1 print *,y end subroutine f(x) x=x**2 return end ****************************************************************************** 这类跳转在F77里经常用到,F90以后并不多见,但对于"100 format (1e12.7)"之类还是经 常用到,这是用来表示存储读取的数据的格式的,可以放在程序任何位置,更具体的用法 要参看说明。 有关注释: Fortran里注释用"!"或"C",其中,一般在Windows下使用"Compad Visual Fortran"编译, 有两种格式,一个是"Free Format",生成".f90",另外一个"Fixed Format",生成".for ",只有".for"里两种注释都可用("!"或"C"),但在".f90"里只能用"!"。 有关学习的困难: 算法是语言的灵魂没错,是最麻烦的,但想必大家都学过C,遇到过不少算法,这些可以用 C实现的,用Fortran实现都不是很困难,所以这里不主要讨论这个“灵魂”性质的东西。 常量、变量、数组的数据类型,以及数据类型的读写控制倒是经常容易出错的。下面主要 讲一些我认为需要注意的和我曾经犯过和看到过的错误。 Fortran跟C一样,也分整型(INTEGER),实型(REAL),双精度(REAL*8或REAL(8)或DOUBLE PRECISION),这些在科学计算中还是比较重要的,以实型数为例: 一般REAL等价于REAL*4或REAL(4),是单精度的; 而双精度在F77中表示为DOUBLE PRECISION,在F90中可以表示为REAL*8或REAL(8),在高精 度计算中,双精度的变量是很有必要的,对于一般实数可以表示为小数形式或指数形式, 而双精度都表示成指数形式,但指数E要改成D,如: REAL:100.0或1e2,双精度下就得表示成1D2 由于Fortran中不需要对每个变量都进行声明,所以有时候会在每个程序或子程序开头做个 说明,如下: IMPLICIT DOUBLE PRECISION(A-H,O-Z) 代表以A-H以及O-Z字母开头的变量默认(在不声明的情况下)是双精度的,否则则是整型 的,如下: ****************************************************************************** PROGRAM D IMPLICIT DOUBLE PRECISION(A-H,O-Z) J1=1D-2 J2=-0.5D-1 x=J1+J2 print *,x end ****************************************************************************** PROGRAM E implicit double precision (A-I,O-Z) double precision a,i,e1,e2 data j2 /0.87450547081842D-3/ data j3 /-0.11886910646016D-4/ data j5 /-0.17242068505339D-5/ data j7 /0.10566966079622D-6/ write(*,*) "please input a" read(*,*) a write(*,*) "please input i" read(*,*) i e1=(j3*sin(i)/(2*a*j2)-5*j5*sin(i)*(1-7*sin(i)**2/2+21*sin(i)**4/8)& &/(2*a**3*(2-5*sin(i)**2/2))+35*j7*sin(i)*(1-27*sin(i)**2/4+99& &*sin(i)**4/8-429*sin(i)**6/64)/(3*a**5*(2-5*sin(i)**2/2))) e2=-(j3*sin(i)/(2*a*j2)-5*j5*sin(i)*(1-7*sin(i)**2/2+21*sin(i)**4/8)& &/(2*a**3*(2-5*sin(i)**2/2))+35*j7*sin(i)*(1-27*sin(i)**2/4+99& &*sin(i)**4/8-429*sin(i)**6/64)/(3*a**5*(2-5*sin(i)**2/2))) write(*,"(E9.2E3)") e1,e2 stop end ****************************************************************************** 第一个程序输出不是-0.4而是0.000000000000000E+000 第二个程序任意输入a、i,并未得到希望得到的结果,而是输出NAN和NAN,关于NAN这个错 误,有时候函数定义域不符合的时候,运行并不报错而是输出NAN,这个时候检查程序这些 地方是检查的重点,当然,会有其他情况,但我碰到的不多,只好就我所知跟大家交流一 下。 这两个程序都因为J开头的变量不属于默认双精度变量,而用双精度表示给它们赋值了,导 致结果跟预期不一致,在程序中把这些以J开头的变量用REAL*8声明一下,或把 implicit double precision (A-I,O-Z)改为: implicit double precision (A-J,O-Z),或把这个语句去掉 就可以得到预期的结果了。 对于数组,可以用DIMENSION定义,但需要注意的是,若在程序头未做声明(implicit none)时,用DIMENSION定义数组时,当数组名首字母不属于(A-J,O-Z)里时,其值输出时 为整型,当然做了如下声明情况也会如此:(implicit double precision (A-I,O-Z)) 如下: ****************************************************************************** PROGRAM F dimension m(2) m(1)=1.5 m(2)=2.5 print *,m(1),m(2) end ****************************************************************************** 输出的结果是“1,2”而不是“1.500000,2.500000” 当把程序中m改为a时,输出“1.500000,2.500000” 所以,比较好的方法是尝试用REAL来定义数组(当然也可以用REAL*8): ****************************************************************************** PROGRAM G real m(2) m(1)=1.5 m(2)=2.5 print *,m(1),m(2) end ****************************************************************************** 另外,要说的是,变量可以不定义而直接赋值,但会出现如上面PROGRAM D-E的问题,所以 建议大家在编程的时候对非整型变量声明一下,尽管麻烦,但不容易出错,有时候正是这 类错误会让初学者困扰好久。 定义变量时,经常会看到两种定义的写法:以REAL为例: 可以有 real m 和 real:: m 第一种方式不可以直接赋值,必须写成这样: ****************************************************************************** PROGRAM H real m m=1.0 print *,m end ****************************************************************************** 第二种则可以: ****************************************************************************** PROGRAM I real:: m=1.0 print *,m end ******************************************************************************
Recent comments
2 weeks 6 days ago
3 weeks 22 hours ago
22 weeks 1 day ago
32 weeks 3 days ago
32 weeks 4 days ago
39 weeks 2 days ago
41 weeks 1 day ago
42 weeks 1 day ago
42 weeks 2 days ago
43 weeks 13 hours ago