当前位置:文档之家› Fortran77-90-95入门

Fortran77-90-95入门

Fortran77-90-95入门
Fortran77-90-95入门

Fortran77-90-95入门

来源于:https://www.doczj.com/doc/2d6312403.html,/yourtommy/article/details/7036301

Fortran语言的历史

Fortran是英文FORmula TRANslation的缩写, 意为"公式翻译". 为科学, 工程问题中那些能够用数学公式表达的问题而设计的语言, 主要用于数值计算. Fortran至今已经有四十多年历史. 第一代Fortran是1954年提出来的, 称为FortranI. 它于1956年在IBM 704计算机上实现的. 是由IBM的John Backus提出并开发的一种容易理解, 简单易学而又像汇编一样高效运行的语言. 1958年出现的FortranII对FortranI进行了很多扩充(如引进了子程序). FortranII在很多机器上实现了. 其后出现的FortranIII因为存在严重的缺陷, 所以没有在任何计算机上实现. 1962年出现的FortranIV并不与FortranII完全兼容.

由于Fortran满足现实需要,所以传播很快, 从而出现了很多的Fortran的版本. 各种版本间语法和语义并不完全一致,所以给用户造成极大不变. 为此, 1962年5月, 当时的美国标准化协会ASA(American Standard Association, 后面改名为ANSI -- American National Standard Institute, 现名为NIST -- National Institute of Standard and Technology)成立工作组开始统一各个版本, 并于1966年正式公布了两个美国标准文本: 标准基本FortranX3.10-1966(相当于FortranII) 和标准FortranX3.9-1966(相当于FortranIV).

由于Fortran在国际上的广泛使用, 1972年国际化标准组织ISO(International Standard Organization)公布了ISO Fortran标准, 即<程序设计语言FortranISO 1953-1972>. 它分为三级: 一级相当于FortranIV,二级介于FortranII和FortranIV之间,三级相当于FortranII.

FortranIV(即Fortran66)流行了十几年,几乎统治了所有的数值计算领域。但它不是结构化语言,没有实现三种基本结构的语句,程序中需要使用GOTO语句来实现特定的算法,美国标准化协会在1976年对FortranX3.9-1966进行修订,把各个版本有效的功能都加入了进来,并加入了新的功能。并在1978年正式公布为美国国家标准ANSI X3.9-1978 Fortran,称作Fortran77。1980年Fortran77被接受成为国际化标准。Fortran77扩充了一些结构化的语句,但不是完全的结构化语言。由于扩充了字符处理功能,Fortran77不仅适用于数值领域,还适用于非数值领域。

之后经过十多年的标准化过程,1991年通过了Fortran90的新标准ANSI X3.198-1991,相应的国际化标准为

ISO/IECI1539:1991。Fortran90保证了Fortran77的兼容性,Fortran77是Fortran90的严格子集。

现在有各种程序设计语言,而且在一些特殊领域使用其它语言会更为合适,但在数值计算、科学和工程领域,Fortran仍然具有强大的优势。随着巨型计算机(向量机和并行机)的异军突起,出现了新的高性能Fortran语言(HPF)。它是Fortran90的一个扩展子集,主要用于分布式内存计算机上的编程,以减轻用户编写消息传递程序的负担。HPF-1.0的语言定义在1992年的超级计算国际会议作出的,正式文本在1993年公布的。1997年发布了HPF-2.0语言定义。Fortran95包含了许多HPF的新功能。在Fortran90出现之前,在并行机上运行程序需要结合专门的矢量化子程序,或者信赖Fortran编译系统进行自动矢量化。而Fortran90之后,程序员可在程序中有目的地控制并行化。Fortran90具有C++的所有重要功能,然而C语言主要用于微机上的廉价开发,而Fortran的目的是产生高效最优化运行的可执行程序。用Fortran编写的大型科学软件较C语言编写的通常要快一个量级。当今不仅大型机,微机和工作站也有了多处理器。高性能并行计算已成必然,串行机上的线性内存模式已不再适用。Fortran作为具有处理相应问题的标准并行化语言,其独特的数组操作充分体现了它的先进性。

第一个Fortran程序

Fortran的程序用.f后缀表示(表示固定格式),下面是一个求算术平均数与几何平均数的代码:

[plain]view plaincopyprint?

1. C-----Fortran固定格式用C开头(必须在行首)表示注释------

2. C每行必须用tab缩进,否则编译错误(严格来说是6个空格)

3. C程序大小写不分

4. C用PROGRAM表示程序开头

5. PROGRAM first_program

6. C定义四个实数

7. real a, b, av1, va2

8. C从标准输入中得到a和b的值

9. READ (*,*) a, b

10. C--av1为a和b的算术平均数

11. av1 = (a+b)/2

12. C--av2为a和b的几何平均数

13. av2 = sqrt(a*b)

14. C在标准输出中显示结果

15. WRITE(*,*) av1, av2

16. C用END表示程序结尾

17. END

1. !-----Fortran自由格式中只能用!开头表示注释,C不能用于注释------

2. PROGRAM first_program !行前不必用tab缩进,但缩进仍然合法

3. REAL a, b, av1, va2

4. rEAd (*,*) a, b !大小写不分

5. av1 = (a+b)/2

6. av2 = sqrt(a*b)

7. WRITE(*,*) av1, av2

8. END

卡片上明示了0~9行,在0行上面为第11行,再上面为第12行。卡片的编码方式与机器以及应用有关。此处11行和12行都不打孔时,0~9行中的一个孔表示一个数字;第11,12,0行中打一个孔以及1~9行中打一个孔表示一个大写字母;第11,12,0行中打一个孔或不打孔、2~7行中打一个孔同时第8行也打一个孔表示一个特殊字符;不打任何孔的列被视为一个空格。正是因为早期的卡片只支持大写字母,所以如今Fortran程序中不区分大小写。

从上面的打孔卡片可以看到,一行Fortran程序(即一张卡片)代表了一条Fortran语句。有时会出现一张卡打不下一行语句,这时再第二张卡片的第6列打一个非0的孔,可以表示该程序行是上一个程序行的续行。前5列是标号区,可以输入5位整数,通常情况下标号区是不允许输入非数字的,但注释除外,第一列为C的语句不会被编译器处理。第7~72列是语句区。而最后8列是在卡片时代方便程序员查找的注释区,不会被编译器处理。

之后的Fortran90格式更加自由。它一行有132列,可以有多条语句,语句之间用分号隔开,语句也没有固定位置的限制。在程序行中字符“!”后的内容都被视为注释(字符串中的“!”除外)。空格也变得有意义了(Fortran77会忽略行中的空格,关键字和变量中可以有空格)。此外如果132列还写不完一行语句的话,可以在末尾加“&”字符表示有续行,续行的开始则用“&”字符来承接上一行。F77里前面5列的10进制整型数由来表示编号,可用于之后的跳转;F90里还可以用英文名加冒号来表示标签,用于跳转。

文件名后缀.f或.for表示固定格式,而.f90表示自由格式。

一个Fortrant程序的组成结构有:

主程序

[PROGRAM 程序名] ←语句可省略

.....

END [PROGRAM [程序名]] ←END必须有

辅程序(过程)

SUBROUTINE 子程序

FUNCTION 函数

BLOCK DATA 块数据

MODULE 模块(F90)

内部过程CONTAINS (F90)

常量与变量

Fortran的常量类型有整型、实型、复型、逻辑型和字符型:

[plain]view plaincopyprint?

1. PROGRAM VARIABLES

2. INTEGER I !整型声明语句

3. REAL F !实型声明语句

4. DOUBLE PRECISION D !双精度声明语句

5. COMPLEX C !复型声明语句

6. LOGICAL B !逻辑型声明语句

7. CHARACTER S !字符型声明语句

8. !整型常量

9. I = -1234 !整型默认为4字节

10. I = -324_8 !8字节整型。下划线加数字表示精度,只允许1,2,4,8个字节

11. I = 123_1 !1字节整型

12. I = 2343_2 !2字节整型

13. I = 238_4 !4字节整型

14. !实型常量

15. F = 23. !以小数点表示实型数,默认为4字节

16. D = 87234.42343256_8 !8字节实型,只允许4或8个字节

17. F = 32.16_4 !4字节实型

18. F = 7.8E9 !指数表示(E字母)

19. D = 8.2384D12 !双精度的指数表示(D字母)

20. !复型常量(C语言里没有的)

21. C = (8.3, 98) !括号里面分别表示实部与虚部

22. !逻辑型常量

23. B = .TRUE. !只能有.TRUE.和.FALSE.两个值

24. B = .FALSE.

25. !字符型常量

26. S = 'a'

27. S = "x" !Fortran90开始允许使用双引号

28. END

上面的代码中可以看到变量的显式声明,在不显式声明的时候,变量名遵循I~N规则,即以I、J、K、L、M、N开头的(未声明的)变量都视为整型变量;其它未声明的变量都被视为实型。比如:

[plain]view plaincopyprint?

1. program implicit_type

2. imax = 85; ! i开头的变量被视为整型

3. nmin = 23; ! n开头的变量也被视为整型

4. phigh = 28.8 ! 其它变量都被视为实型

5. end

1. program implicit_type

2. implicit real (i-k) !i,j,k开头的变量都会被视为实型

3. implicit integer (a,d,x-z) !a,d,x,y,z开头的变量都会被视为整型

4. implicit complex (c) !c开头的变量会被视为复型

5. end

1. read *, iValue

2. !单行if语名

3. if (iValue > 0) print *, iValue, " is greater than 0"

4. !if then else语句块

5. if (ivalue > 5) then

6. iValue = 5

7. else if (ivalue > 0) then

8. iValue = 0

9. else

10. iValue = -5

11. end if

12. print *, iValue

1. !整型case,不支持实型case和复型case

2. read *, iValue

3. select case (iValue)

4. case (3) !当值为3时

5. print *, "It's 3!"

6. case (6:) !当下界为6时(大于等于)

7. print *, "above 6"

8. case (:0) !当上界为0时(小于等于)

10. case (4:5) !当在4到5之间时(小于等于下界大于等于上界)

11. print *, "between 4 and 5"

12. case default !其它情况

13. print *, "default"

14. end select

15. !字符型case

16. read *, cValue

17. select case (cValue)

18. case ("x")

19. print *, "it's x!"

20. case ("a":"g")

21. print *, "between a~g"

22. case default

23. print *, "other"

24. end select

25. !逻辑型case

26. read *, iValue

27. select case (iValue > 0)

28. case (.true.)

29. print *, "positive"

30. case (.false.)

31. print *, "negtive or zero"

32. end select

1. !固定循环次数的do循环

2. !不带标号的do

3. do i=1, 20, 1 !类似于C里的for(i=1,i<=20,i+=1)

4. print *, i

5. end do

6. !省略最后的增量

7. do i=1, 20 !仍然每次递增1

8. print *, i

9. end do

10. !带标号的do

11. do 123, i=20, 0, -2 !do后是标号,即从123处开始循环

12. print *, i

13. 123 continue !循环终端。该行有标号。可以用end do代替,比较过时

15. !在读写语句里可以控制读写的次数

16. print *, (i*5, i=1,20)

17. !可以嵌套循环

18. write (*,*) ((i,j,i=1,5),j=6,9) !i为内层循环,j为外层循环

19. !无限循环

20. do

21. print *, "I'm here!"

22. read *, i

23. if (i > 5) cycle !cycle回到循环起点,类似于C的continue

24. print *, "not greater than 5!"

25. if (i < 0) exit !exit用于退出循环,类似于C的break

26. end do

27. !用标签来控制嵌套循环的流程

28. outer: do

29. print *, "I'm in outer!"

30. inner: do

31. print *, "I'm in inner!"

32. read *, i

33. if (i > 0) exit inner !跳出内循环

34. if (i < 0) exit outer !直接跳出外循环

35. end do inner !必须接标签名

36. end do outer

37. !do while循环

38. i = 0

39. do while (i < 20)

40. print *, "in while", i

41. i = i+1

42. end do

1. !程序退出

2. stop 1 !类似于C的exit(1)

3. print *, "skipped" !这行不会被执行

1. program string

2. character c

3. character*8 :: s

4. !字符与数值的转换

5. iValue = ichar("a") !97-返回字符的序号值

6. iValue = iachar("a"); !97-返回字符的ascii码

7. !iValue = iachar("ab") !Error: Argument of IACHAR at (1) must be of length one

8. c = char(97) !a-返回序号值对应的字符

9. c = achar(97) !a-返回ascii码对应的字符

10. !字符串的长度

11. iLen = len("abcdefg"); !7

12. iLen = len("abcdefg "); !9

13. iLen = len_trim("abcdefg "); !7 去除尾部空格后的长度

14. !查找子串,找不到返回0

15. iIndex = index("abcdefg", "cde"); !3

16. iIndex = index("abcdefg", "abcxyz"); !0

17. !验证第一个参数里的所有字符是否属于第二个参数表示的字符集,如果都属于则返回0,否则返回

18. 第一个不属于字符集的索引。

19. iIndex = verify("bcd", "abcdefg"); !0

20. iIndex = verify("bcdxyz", "abcdefg"); !4

21. !去除末尾的空格

22. s = trim("abcd ") // "efg" !abcdefg

23. end

1. program type_demo

2. type one

3. integer a

4. character*16 s

5. end type

6.

7. type :: two

8. sequence !表示按定义的顺序储存各个成员

9. logical(8):: b

10. complex :: c = (23, 9.8) !可以缺省初始化

11. end type

12.

13. type(one):: o1, o2 = one(18, "xyz");

14. type(two):: t1;

15. t1%b = .true.

16. print *, o2%a, o2%s

17. end

1. !声明数组

2. real a(10) !下标从1到10的一维数组

3. integer b(-5:8) !下标从-5到8的一维数组

4. dimension iArray(4) !根据i~n规则确定为是整型或实型数组

5. character*8, dimension(2:5) :: sa !类型声明形式

6. integer indices(3)

7.

8. !赋初值

9. data a /10*3/ !赋成10个3

10. data b(-3), b(0), b(3) /1, 2, 3/ !把选中的三个元素分别赋成1,2,3

11. data (iArray(i),i=1,4) /4*2/ !把所有元素赋为2

12.

13. !数组的存取

14. print *, "input 10 elements:"

15. read *, (a(i), i=1,10) !读入数组a的所有元素

16. a(1) = a(1) + 2

17. a(2:4) = 5 !把a(2)、a(3)和a(4)都设为5。a(2:4)等价于a(2:4:1)

18. print *, (a(i), i=1,5) !打印前5个值

19.

20. !三元下标

21. b(:) = 8 !打b中的所有元素都设为8

22. b(1:6:2) = 7 !把b(1)、b(3)、b(5)设为7,三元下标(起始:终止:增量)

23. b(:-3) = 3 !把b(-5)、b(-4)、b(-3)设为3.默认起始为数组开头。

24. b(6::2) = 9 !把b(6)和b(8)设为9,默认终止为数组末尾

25. print *, b

26.

27. !向量下标

28. indices = (/3, 8, 6/)

29. a(indices) = 13 !把a(3)、a(8)、a(6)设为13

30. print *, a

1. integer :: a(10, 5) = 77 !大小为10x5的数组,所有的元素值都为77

2. a(:,2:3) = 8 !把每行的2,3列都设为8

3. print *, ((a(i,j), i=1,10), j=1,5)

1. subroutine automatic_array(N)

2. integer a(N)

3. a(:) = 8

4. print *, a

5. end

1. subroutine adjustable_array(A, N)

2. integer A(N)

3. print *, A

4. end

1. interface

2. !假定形状(assumed-shape)数组

3. subroutine assumed_shape_array(A)

4. integer A(:,:) !假定是个二维数组

5. end subroutine

6. end interface

[plain]view plaincopyprint?

1. subroutine assumed_size_array(A)

2. integer A(2,2,*)

3. print *, A(:,:,1)

4. end

1. integer a(6)

2. integer b(8)

3. a = (/1,2,3,4,5,6/) !长度必须一样,否则编译会出错

4. print *, a

5. a = (/3,2,3,4,7,8/) !可以多次对数组进行赋值

6. print *, a

7. a = [4,8,9,2,1,5] !方括号与(/.../)方式等价

8. print *, a

9.

10. b = (/1,2,a(1:4),8,9/) !数组方式

11. print *, b

12. b = (/(i*2,i=1,4),a(3:6)/) !隐do方式

13. print *, b

1. integer :: a(9) = (/(i,i=1,9)/)

2. a(2:9) = a(1:8) !并行方式

3. print *, a ! 1 1 2 3 4 5 6 7 8

4.

5. a = (/(i,i=1,9)/)

6. do i=2,9

7. a(i) = a(i-1) !串行方式

8. end do

9. print *, a ! 1 1 1 1 1 1 1 1 1

1. integer b(2,3)

2. b = reshape((/1,2,3,4,5,6/), (/2,3/))

3. print *, b

4. b = reshape((/1,2,3/), (/2,3/), (/8,9/))

5. print *, b !1,2,3,8,9,0。补充数组的元素仍不够的情况下补0

6. b = reshape((/1,2,3,4,5/), (/2,3/), (/8,9/), (/2,1/))

7. print *, b !1,4,2,5,3,8。顺序2,1说明先填满第一个维度(即行),再来填第二个维度(即列)。

1. integer A(5), B(5), C(5)

2. A = (/1,2,3,4,5/)

3. B = (/3,3,3,3,3/)

4. C = (/0,0,0,0,0/)

5. where (A >= B) C = A

6. print *, C ! 0,0,3,4,5

7.

8. where (A < B)

9. C = -1

10. elsewhere (A == B)

11. C = 0

12. elsewhere

13. C = 1

14. end where

15. print *, C ! -1,-1,0,1,1

1. integer A(5, 5)

2. A = reshape((/(i,i=1,25)/), (/5,5/))

3. forall(i=2:3,j=1:5:2) A(i,j) = 0

4. print *, A

1. integer A(2,3), B(2,3), C(2,3)

2. logical P(2,3), Q(2,3), R(2,3)

3. real X(2,2), Y(2,2)

4.

5. !算术运算

6. A = reshape((/(i,i=1,6)/), (/2,3/))

7. B = 2

8. C = A + B

9. print *, C

10. C = A - B

11. print *, C

12. C = A * B

13. print *, C

14. C = A / B

15. print *, C

16.

17. !比较运算

18. P = A < B

19. print *, P

20. Q = A > B

21. print *, Q

22.

23. !逻辑运算

24. R = P .and. Q

25. print *, R

26. R = P .or. Q

27. print *, R

28. R = .not. P

29. print *, R

30.

31. !基本内在函数

32. X = reshape((/1.,2.,3.,4./), (/2,2/))

33. Y = cos(X)

34. print *, Y

35. Y = sin(X)

36. print *, Y

37. Y = sqrt(X)

38. print *, Y

1. INTEGER, ALLOCATABLE :: A(:),B(:)

2. INTEGER ERR_MESSAGE

3. ALLOCATE(A(10:25),B(SIZE(A)),STAT=ERR_MESSAGE)

4. IF(ERR_MESSAGE.NE.0) PRINT *,'ALLOCATION ERROR'

1. program procedures

2. implicit none

3. integer:: x=5,y=6,res=0

相关主题
文本预览
相关文档 最新文档