y

yhyhyh

V1

2023/01/14阅读:27主题:默认主题

Fortran学习笔记丨函数、子例行程序与模块

Fortran学习笔记丨函数、子例行程序与模块

目录:

函数与子程序

函数:FUNCTION

子(例行)程序:SUBROUTINE

语句函数

语句函数的一般形式为:

F(X1, X2, X3, ..., XN) = EXPRESSION

函数名:函数名的命名规则与变量名相同。需要先指明函数名的类型(即返回值的类型)

形式参数列表:以圆括号()包围,里面可以没有内容,但是不能删除圆括号()

EXPRESSION :不能出现函数名本身,但可以使用定义过的函数。只能有一个返回值。只能一个语句定义完。

例子:

PROGRAM E61
	IMPLICIT NONE
	
	! 检测语句函数
	! 实现三角形面积的计算(海伦公式)
	
	REAL*8 A,B,C,S,AREA
	
	REAL*8 F1, F2
	! F1是计算三角形半周长
	! F2是计算三角形面积
	REAL*8 X1,X2,X3,XS
	
	! 需要在程序声明部分定义语句函数
	F1(X1, X2, X3) = (X1+X2+X3)/2.0
	F2(XS, X1,X2,X3) = SQRT(XS*(XS-X1)*(XS-X2)*(XS-X3))
	
	PRINT*, "PLEASE INPUT A,B,C OF THE TRIANGULAR:"
	READ(*,*) A,B,C
	S = F1(A,B,C)
	AREA = F2(S,A,B,C)
	WRITE(*,"('THE AREA IS:',F15.8)") AREA
	
END PROGRAM E61

内部函数

内部函数的一般格式为:

FUNCTION <func_name>(<argument_list>)
	! specification of <func_name> and <args>
	! some executation...
END FUNCTION <func_name>

内部函数的特点:

  • 只能被本程序调用,函数的定义与调用在PROGRAM以内

  • 函数的返回值等于函数名,必须指定函数名的类型;或者可以另外指定返回值的名称,请检索result关键字的用法。

  • 指定函数类型可以在函数体中进行,也可以在函数头进行;

  • 函数的执行语句中不能出现函数名本身(即不能出现递归调用)

  • 形式变量可以声明三种属性:

    • INTENT(IN):函数可以从变量获得值,但是不能改变内容
    • INTENT(OUT):函数可以改变变量的内容
    • INTENT(INOUT):函数即可以获得值、也可以改变内容
  • 形式变量列表可以为空。(这是显而易见的、合理的)

  ! 在函数头定义了函数的返回值类型是REAL类型
  REAL FUNCTION LARGER_VALUE()
  	...
  END FUNCTION
  
  
  ! 在函数体中声明函数的返回类型
  FUNCTION LARGER_VALUE()
  	...
  	REAL::LARGER_VALUE
  	...
  END FUNCTION

内部函数举例:

PROGRAM E62
	! 内部函数举例;海伦公式计算三角形面积
	IMPLICIT NONE
	REAL*8 A,B,C,AREA
	
	PRINT*, "PLEASE INPUT THE A,B,C OF THE TRIANGULAR: "
	READ(*,*) A,B,C
	
	AREA = F(A,B,C)
	
	WRITE(*,"('AREA = ',F9.3)") AREA
	
	READ(*,*)
CONTAINS
	! FUNCTION F(A,B,C)的定义
	FUNCTION F(A,B,C)
		REAL*8 F,A,B,C
		REAL*8 S
		S = (A+B+C)/2.0
		F = SQRT(S*(S-A)*(S-B)*(S-C))
	END FUNCTION F
END PROGRAM E62

外部函数

所谓“外部函数”,与“内部函数”对比:定义在PROGRAM以外,且在PROGRAM调用之前需要做声明,可以调用其他函数或调用自己。

在主程序中声明外部函数,可以用EXTERNAL关键字,或者INTERFACE接口块。

举例:定义了CAL_AVERAGECAL_TRI_AREA函数。在主函数的变量声明部分,需要声明函数名变量。

(1)用EXTERNAL关键字:

REAL, EXTERNAL :: CAL_AVERAGE, CAL_TRI_AREA

或者:

EXTERNAL CAL_AVERAGE, CAL_TRI_AREA
REAL :: CAL_AVERAGE, CAL_TRI_AREA

(2)使用INTERFACE接口块:

...
INTERFACE
	REAL FUNCTION CAL_AVERAGE(A,B,C)
		REAL, INTENT(IN) :: A,B,C
	END FUNCTION CAL_AVERAGE
	
	REAL FUNCTION CAL_TRI_AREA(A,B,C)
		REAL, INTENT(IN) :: A,B,C
		REAL :: S	! 注意,声明所有的变量,不仅是形参
	END FUNCTION CAL_TRI_AREA
END INTERFACE
...

子例行程序

子例行程序的特点:

  • 子例行程序常用来打印、输入、输出等操作,或者数组运算、交换数据等产生多个处理结果的操作;
  • 子例行程序的程序名不能作为返回值;但是可以通过形式变量对传入的值进行改变。形式变量的INTENT属性与函数相同。
  • 外部子例行程序在PROGRAM中同样需要声明,声明方法与函数相同(用EXTERNAL关键字,或者INTERFACE接口块)。
  • 子例行程序的形参列表也是用圆括号()包围,但是如果没有形参,那么定义与调用时都可以省略圆括号()

子例行程序的调用需要用到关键字CALL。例如:

PROGRAM E63
	! 子例行程序学习;交换两个数
	IMPLICIT NONE
	
	INTERFACE
		SUBROUTINE SWAP(A,B)
			REAL*8,INTENT(INOUT)::A,B
			REAL*8::TMP
		END SUBROUTINE SWAP
	END INTERFACE
	
	REAL*8 A,B,C
	
	PRINT*, "PLEASE INPUT 3 NUMBERS: "
	READ(*,*) A,B,C
	
	! 从小到大输出三个数
	IF (A.GT.B) CALL SWAP(A,B)
	IF (B.GT.C) CALL SWAP(B,C)
	IF (A.GT.B) CALL SWAP(A,B)
	
	PRINT*, 'THE NUMBERS FROM SMALL TO LARGE: '
	WRITE(*,"(3(F9.3))") A,B,C
	
	READ(*,*)
	
END PROGRAM E63

! 外部子例行程序SWAP
SUBROUTINE SWAP(A,B)
	REAL*8,INTENT(INOUT)::A,B
	REAL*8::TMP
	
	TMP = A
	A = B
	B = TMP
END SUBROUTINE SWAP

模块(Module)

模块一般放在单独的源文件里面。模块的一般格式为:

MODULE <module_name>
	IMPLICIT NONE
	[SPECIFICATION_PART]
	! 例如一些变量的声明
	CONTAINS
		[INTERNAL_SUBPROGRAMS]
		! 例如一些function与subroutine的定义
END MODULE <module_name>

模块的使用:USE关键词与ONLY关键字

USE <module_name>

或者

USE <module_name>, ONLY : name_1, name_2, ...

其中的name可以是变量或子程序。

举例(一个极简单的例子):

工作区的源文件包括:

the_modules.f90

MODULE FACT_MODULE
	IMPLICIT NONE
CONTAINS
	FUNCTION FACTORIAL(N)
		IMPLICIT NONE
		INTEGER*8,INTENT(IN)::N
		INTEGER*8::FACTORIAL
		INTEGER*8::FACT, I
		
		FACT = 1
		DO I=1,N
			FACT = FACT * I
		END DO
		FACTORIAL = FACT
	END FUNCTION FACTORIAL
	
	FUNCTION C(N,R)
		! 计算组合数C(N,R)
		IMPLICIT NONE
		
		INTEGER*8::C
		INTEGER*8,INTENT(IN)::N,R
		INTEGER*8::C_TMP
		
		IF (0 .LT. R .AND. R .LT. N) THEN
			C_TMP = FACTORIAL(N)/&
			(FACTORIAL(N-R)*FACTORIAL(R))
		ELSE
			C_TMP = 0
			! 对于无效的参数
		END IF
		
		C = C_TMP
		
	END FUNCTION C
	
END MODULE FACT_MODULE

以及,

main.f90

PROGRAM MAIN
	! 使用模块的方法,计算组合数
	! 先引入模块,再写implicit none
	USE FACT_MODULE
	
	IMPLICIT NONE
	
	INTEGER*8 :: N,R
	INTEGER :: MASK
	
	MASK = 1
	DO
		READ(*,*) N,R
		IF (N>=0 .AND. R>=0) THEN
			WRITE(*,"(I9,'! = ',I9)") N,FACTORIAL(N)
			WRITE(*,"(I9,'! = ',I9)") R,FACTORIAL(R)
		ELSE
			EXIT
		END IF
		
		IF (R<=N) THEN
			WRITE(*,"('C(',I6,',',I6,') = ',I9)") &
			N,R,C(N,R)
		ELSE
			WRITE(*,*) "ERROR! C = -1"
		END IF
		
	END DO
	
END PROGRAM

在Windows平台用以下的命令编译:

gfortran -c the_modules.f90

gfortran -o main.exe main.f90 the_modules.o

可以得到可执行文件。

分类:

数学

标签:

数学编程

作者介绍

y
yhyhyh
V1