给fortran新手的一些实用建议

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Fortran 导引
1、 Fortran 学习的一些建议
相信大家都对 C 语言有一定的了解,其实 Fortran 跟 C 相差不是很多。 我把自己认为比较合理快速学习 Fortran 的方法说下。 学习 Fortran,会遇到 Fortran77&Fortran90 等等,两者差别不大,建议学习 Fortran90 或更高,更加自由些(仅 对一般用而言,其他优势可能体现不出来),对自己以后Байду номын сангаас习他的程序包也会有好处。 大家一般只是为了编程,为了计算而学 Fortran,而不是为了学习 Fortran 而学 Fortran,所以我的建议是学习 Fortran 不要像学 C 那样拿一本很详细的教材从头至尾学下来,一个大家都有不错的 C 语言基础,而且也没有太多 的精力去专门研究这些,倒不如看些简易的教材(我会附上),掌握基本语句之后直接从看最简单的程序开始。这 样,很快就会体会到 Fortran 的格式,可以开始自己写程序了。学习的顺序我建议如下: 1、 编一些仅含输入输出的程序,然后可以尝试把输入输出同文件结合起来(从文件里读数据、写数据); 2、 然后可以学条件判断、循环语句,通过几个实例也可以很快掌握; 3、 再往后就是写子程序,就是程序的调用,相信那个时候,看了我的第一个例子(PROGRAM 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')
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 ******************************************************************************
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,如:
相关文档
最新文档