Fortran知识点
来源:互联网 发布:数据挖掘技术有哪些 编辑:程序博客网 时间:2024/05/21 01:43
Fortran中子函数所带参数叫虚参,如subroutine sub(da) da叫做虚参,而对应的主调函数call sub(aa) aa叫做实参,在此直说明一下让人费解的假定大小数组说明符。
所谓的假定大小数组说明符是指:在子程序中,可以使用“*”号作为虚参数组的数组说明符中最后一个维定义符的上届。它的作用是所定义的虚数组的大小和与之对应的实参数组大小完全相同,也就是说,当子程序未被调用时,虚数组的大小是假定的,假定与所对应的实参数组大小相同。
注:这种假定大小数组说明符只能在子程序中对虚参数组使用。
interface 功能详解
本文详细介绍了interface用作接口界面块、函数重载和操作符重载时的用法。
接口界面块:Interface 功能详解
说明:子程序可看做无返回值的函数,为了方便叙述,如未特别说明,文中将函数(function)和子程序(subroutine)统称为函数。
函数的接口信息用于告诉编译器应该如何正确调用该函数,它包括参数和返回值的数量、类型等信息。因此每个函数都必须具有相应的接口信息,缺省情况具有隐式声明,而使用interface则可显式声明函数的接口信息。
Interface 的主要功能:
1、明确外部函数(external procedure) 或虚函数(dummy procedure)的接口信息,包括:输入输出参数的类型和属性、返回值类型、函数属性;
2、定义通用过程名,即函数重载(overload);
3、操作符(+,-,*,/,et al)和赋值符(=)重载。
下面将分别对以上三种功能进行说明。
1、接口界面块
内部函数(contains)、模块(module)中的函数,以及Fortran标准函数 (如:sind、abs等) 均自动包含显式接口,不需要也不能再次声明接口信息,因此上述情况不在讨论之中。我们建议将外部函数封装在module中使用。
外部函数缺省具有隐式接口,对一些常规函数,用户不必显示声明其接口信息,编译器也能正确识别。但当外部函数的形参具有ALLOCATABLE, ASYNCHRONOUS, OPTIONAL, POINTER, TARGET, VALUE, VOLATILE属性时,必须显示声明接口信息。下列情况之一也必须使用接口界面块:
● 外部函数返回值为指针、数组或可变长度字符串;
● 形参为数组片段;
● 参数个数不确定或包含可选参数;
● 改变参数传递顺序;
● 子程序中扩展了赋值号的使用范围。
接口界面块的使用较为简单,在接口界面块(interface-end interface)之间写入函数形参类型说明语句,即去掉所有可执行语句后的剩余部分。下面的例子给出了函数返回数组时以及具有可选参数时使用interface的例子:
2、函数重载
某些情况下,我们需要对不同类型或不同数量的参数做相似或相同的操作,由于参数类型、数量不同,我们需要编写不同的函数来处理。比如求绝对值,如果参数是4字节整数,我们需要调用iabs函数;如果参数是4字节或8字节实数,我们需要分别调用abs或dabs函数。
由于需要记住多个功能相同或相近的函数,增加了我们使用这些函数的难度,同时也增加了出错的可能性,比如将实数传递给iabs函数。
上述函数的功能相同,只是参数类型或个数不同,那么可否使用同一个函数名来执行它们呢?当然可以,这就是函数重载。函数重载允许通过调用通用过程名来执行特定函数。当用户调用通用过程名时,编译器首先检查传入参数的类型和数量,再调用与之匹配(类型和数量相同)的特定函数来执行具体任务。
例如我们建立通用过程名abs来求绝对值,用户在任何情况都只需调用abs,编译器会自动选用合适的特定函数执行对应操作:当传入参数是4字节整数,就调用iabs函数;如果是8字节实数,则调用dabs函数。
下面用求绝对值的例子说明函数重载功能。为与Fortran内在函数abs区别开来,我们在函数名后添加“_f”。
执行结果:
2.000000
3.00000000000000 3.00000000000000
4 4
代码分析:我们使用interface创建了一个函数重载,其通用过程名(interface之后的标识符)为abs_f,包含三个特定过程abs_f, dabs_f, iabs_f。需要注意,通用过程名可以与其中一个特定过程名一致,也可以不一致;但特定过程名之间必须不同。每个特定过程的形参类型和数量不能完全一致。
interface abs_f
module procedure abs_f, dabs_f, iabs_f
end interface
在程序执行过程中,调用通用过程名时,编译器首先检查实参的类型和数量,并与特定过程的接口信息相匹配。如果匹配成功,则调用相应特定函数(故dabs_f(y)和abs_f(y)的结果是一致的);否则编译器会报错。
比如调用 abs_f(12_8), 由于我们没有给出针对8字节整数求绝对值的特定函数,编译器则会报错。
3、操作符和赋值符(=)重载
常规运算中,我们经常用到算术操作符(+,-,*,/,**)、关系操作符(<,<=,>,>=,==,/=)以及赋值符(=),同时也会发现其使用具有一定的局限性:只能对特定的数据类型进行运算,不能直接用于派生数据类型。
比如两个时间相减,我们不能直接使用“-”进行操作,而需要编写特定的函数。针对这一问题,Fortran90引入了操作符重载功能。我们先看下面一段代码:
模块time_class中定义了一个时间类结构体以及两个函数,函数timeMinus用于操作符“-”重载和自定义操作符,子程序assign_time用于赋值符“=”重载。注意,操作符重载只能使用function,而赋值符重载只能使用subroutine,自定义操作符需位于两个dot之间。
程序一开始使用赋值符重载功能对time1和time2进行赋值,由于数据无误,正常执行;
接下来,分别使用重载操作符“-”和自定义操作符“.minus.”进行两个时间相减,得到相应结果;
最后对time1赋值时,由于数据有误,输出错误提示。
执行结果:
21 8 9
19 4 11
Time类数据错误.
说明:子程序可看做无返回值的函数,为了方便叙述,如未特别说明,文中将函数(function)和子程序(subroutine)统称为函数。
函数的接口信息用于告诉编译器应该如何正确调用该函数,它包括参数和返回值的数量、类型等信息。因此每个函数都必须具有相应的接口信息,缺省情况具有隐式声明,而使用interface则可显式声明函数的接口信息。
Interface 的主要功能:
1、明确外部函数(external procedure) 或虚函数(dummy procedure)的接口信息,包括:输入输出参数的类型和属性、返回值类型、函数属性;
2、定义通用过程名,即函数重载(overload);
3、操作符(+,-,*,/,et al)和赋值符(=)重载。
下面将分别对以上三种功能进行说明。
1、接口界面块
内部函数(contains)、模块(module)中的函数,以及Fortran标准函数 (如:sind、abs等) 均自动包含显式接口,不需要也不能再次声明接口信息,因此上述情况不在讨论之中。我们建议将外部函数封装在module中使用。
外部函数缺省具有隐式接口,对一些常规函数,用户不必显示声明其接口信息,编译器也能正确识别。但当外部函数的形参具有ALLOCATABLE, ASYNCHRONOUS, OPTIONAL, POINTER, TARGET, VALUE, VOLATILE属性时,必须显示声明接口信息。下列情况之一也必须使用接口界面块:
● 外部函数返回值为指针、数组或可变长度字符串;
● 形参为数组片段;
● 参数个数不确定或包含可选参数;
● 改变参数传递顺序;
● 子程序中扩展了赋值号的使用范围。
接口界面块的使用较为简单,在接口界面块(interface-end interface)之间写入函数形参类型说明语句,即去掉所有可执行语句后的剩余部分。下面的例子给出了函数返回数组时以及具有可选参数时使用interface的例子:
01
program
Fcode_cn
02
integer
::
i
=
0
,
j
=
1
,
k
=
2
,
m
(
2
)
03
04
interface
! 接口块
05
subroutine
sub
1
(
i
,
j
,
k
)
06
integer
,
optional
::
k
07
integer
i
,
j
08
end
subroutine
09
10
function
func
1
(
j
,
k
)
11
integer
j
,
k
12
integer
func
1
(
2
)
13
end
function
14
end
interface
15
16
m
=
func
1
(
j
,
k
)
17
print
*
,
m
! m=3,-1
18
19
call
sub
1
(
i
,
j
,
k
)
20
print
*
,
i
! i=3
21
22
call
sub
1
(
i
,
j
)
23
print
*
,
i
! i=1
24
25
pause
26
end
27
28
function
func
1
(
j
,
k
)
29
integer
j
,
k
30
integer
func
1
(
2
)
31
func
1
(
1
)
=
j
+
k
32
func
1
(
2
)
=
j
-
k
33
end
function
34
35
subroutine
sub
1
(
i
,
j
,
k
)
36
integer
,
optional
::
k
37
integer
i
,
j
38
if
(
present
(
k
)
)
then
39
i
=
j
+
k
40
else
41
i
=
j
42
end
if
43
end
subroutine
2、函数重载
某些情况下,我们需要对不同类型或不同数量的参数做相似或相同的操作,由于参数类型、数量不同,我们需要编写不同的函数来处理。比如求绝对值,如果参数是4字节整数,我们需要调用iabs函数;如果参数是4字节或8字节实数,我们需要分别调用abs或dabs函数。
由于需要记住多个功能相同或相近的函数,增加了我们使用这些函数的难度,同时也增加了出错的可能性,比如将实数传递给iabs函数。
上述函数的功能相同,只是参数类型或个数不同,那么可否使用同一个函数名来执行它们呢?当然可以,这就是函数重载。函数重载允许通过调用通用过程名来执行特定函数。当用户调用通用过程名时,编译器首先检查传入参数的类型和数量,再调用与之匹配(类型和数量相同)的特定函数来执行具体任务。
例如我们建立通用过程名abs来求绝对值,用户在任何情况都只需调用abs,编译器会自动选用合适的特定函数执行对应操作:当传入参数是4字节整数,就调用iabs函数;如果是8字节实数,则调用dabs函数。
下面用求绝对值的例子说明函数重载功能。为与Fortran内在函数abs区别开来,我们在函数名后添加“_f”。
01
module
abs_module
02
implicit
none
03
interface
abs_f
04
module
procedure
abs_f
,
dabs_f
,
iabs_f
05
end
interface
06
contains
07
function
abs_f
(
x
)
08
real
(
4
)
abs_f
,
x
09
if
(
x
<
0.0
_
4
)
then
10
abs_f
=
-
x
11
else
12
abs_f
=
x
13
end
if
14
end
function
abs_f
15
16
function
dabs_f
(
x
)
17
real
(
8
)
dabs_f
,
x
18
if
(
x
<
0.0
_
8
)
then
19
dabs_f
=
-
x
20
else
21
dabs_f
=
x
22
end
if
23
end
function
dabs_f
24
25
function
iabs_f
(
x
)
26
integer
(
4
)
iabs_f
,
x
27
if
(
x
<
0
)
then
28
iabs_f
=
-
x
29
else
30
iabs_f
=
x
31
end
if
32
end
function
iabs_f
33
end
module
abs_module
34
35
program
Fcode_cn
36
use
abs_module
37
real
(
4
)
::
x
=
-2.0
_
4
38
real
(
8
)
::
y
=
-3.0
_
8
39
integer
(
4
)
::
z
=
-4
40
41
print
*
,
abs_f
(
x
)
42
print
*
,
dabs_f
(
y
)
,
abs_f
(
y
)
43
print
*
,
iabs_f
(
z
)
,
abs_f
(
z
)
44
45
pause
46
end
执行结果:
2.000000
3.00000000000000 3.00000000000000
4 4
代码分析:我们使用interface创建了一个函数重载,其通用过程名(interface之后的标识符)为abs_f,包含三个特定过程abs_f, dabs_f, iabs_f。需要注意,通用过程名可以与其中一个特定过程名一致,也可以不一致;但特定过程名之间必须不同。每个特定过程的形参类型和数量不能完全一致。
interface abs_f
module procedure abs_f, dabs_f, iabs_f
end interface
在程序执行过程中,调用通用过程名时,编译器首先检查实参的类型和数量,并与特定过程的接口信息相匹配。如果匹配成功,则调用相应特定函数(故dabs_f(y)和abs_f(y)的结果是一致的);否则编译器会报错。
比如调用 abs_f(12_8), 由于我们没有给出针对8字节整数求绝对值的特定函数,编译器则会报错。
3、操作符和赋值符(=)重载
常规运算中,我们经常用到算术操作符(+,-,*,/,**)、关系操作符(<,<=,>,>=,==,/=)以及赋值符(=),同时也会发现其使用具有一定的局限性:只能对特定的数据类型进行运算,不能直接用于派生数据类型。
比如两个时间相减,我们不能直接使用“-”进行操作,而需要编写特定的函数。针对这一问题,Fortran90引入了操作符重载功能。我们先看下面一段代码:
01
module
time_class
02
implicit
none
03
type
time
!定义一个时间类结构体
04
integer
(
1
)
hour
,
minute
,
second
05
end
type
06
interface
operator
(
-
)
!重载操作符-
07
module
procedure
timeMinus
08
end
interface
09
interface
assignment
(
=
)
!重载赋值符=
10
module
procedure
assign_time
11
end
interface
12
interface
operator
(
.minus.
)
!自定义操作符.minus.
13
module
procedure
timeMinus
14
end
interface
15
contains
16
! 两个时间相减
17
function
timeMinus
(
time
1
,
time
2
)
18
type
(
time
)
,
intent
(
in
)
::
time
1
,
time
2
19
type
(
time
)
timeminus
20
integer
n
21
n
=
(
time
1
.hour
-
time
2
.hour
)
*
3600
+
(
time
1
.minute
-
time
2
.minute
)
*
60
+
(
time
1
.
second
-
time
2
.
second
)
22
if
(
n
<
0
)
n
=
n
+3600
*
24
23
timeminus.
second
=
mod
(
n
,
60
)
24
n
=
n
/
60
25
timeminus.minute
=
mod
(
n
,
60
)
26
timeminus.hour
=
n
/
60
27
end
function
28
! 如果time类数据正确,将其赋值给res;否则输出错误提示
29
subroutine
assign_time
(
res
,
time
1
)
30
type
(
time
)
,
intent
(
in
)
::
time
1
31
type
(
time
)
,
intent
(
out
)
::
res
32
if
(
time
1
.hour
>=
0
.and.
time
1
.hour
<=
23
)
then
33
if
(
time
1
.minute
>=
0
.and.
time
1
.minute
<=
59
)
then
34
if
(
time
1
.
second
>=
0
.and.
time
1
.
second
<=
59
)
then
35
res.hour
=
time
1
.hour
36
res.minute
=
time
1
.minute
37
res.
second
=
time
1
.
second
38
return
39
end
if
40
end
if
41
end
if
42
write
(
*
,
*
)
"time类数据错误."
43
end
subroutine
44
end
module
45
46
program
fcode_cn
47
use
time_class
48
type
(
time
)
time
1
,
time
2
,
time
3
49
time
1
=
time
(
2
,
3
,
58
)
50
time
2
=
time
(
23
,
12
,
7
)
51
time
3
=
time
2
-
time
1
!重载操作符-
52
print
*
,
time
3
53
time
2
=
time
3
.minus. time
1
!自定义操作符.minus.
54
print
*
,
time
2
55
time
1
=
time
(
25
,
5
,
6
)
!重载赋值符=
56
pause
57
end
模块time_class中定义了一个时间类结构体以及两个函数,函数timeMinus用于操作符“-”重载和自定义操作符,子程序assign_time用于赋值符“=”重载。注意,操作符重载只能使用function,而赋值符重载只能使用subroutine,自定义操作符需位于两个dot之间。
程序一开始使用赋值符重载功能对time1和time2进行赋值,由于数据无误,正常执行;
接下来,分别使用重载操作符“-”和自定义操作符“.minus.”进行两个时间相减,得到相应结果;
最后对time1赋值时,由于数据有误,输出错误提示。
执行结果:
21 8 9
19 4 11
Time类数据错误.
0 0
- Fortran知识点
- fortran 知识点集合
- Fortran
- fortran
- fortran
- 什么是Fortran
- Fortran FAQ
- FORTRAN简介
- fortran教程
- fortran简介
- Fortran接口
- Fortran接口
- Fortran 数组
- OpenMP & Fortran
- fortran学习
- fortran数组
- fortran函数
- fortran指针
- AngularJS Tutorial(10)from w3school
- Babelfish
- org.hibernate.MappingException: Could not determine type for: String, at table: Elec_SystemDDL, for
- 关于c++中getline(cin,str)在cin之后使用
- 关于EmberJs的一些规范
- Fortran知识点
- MySQL数据库与表创建常用命令
- AngularJS Tutorial(11)from w3school
- Top HTML5 Frameworks in 2015
- 处理乘法取模爆long long 的方法
- POJ 3907 Build Your Home
- Android学习心得(10) --- MAC下Android反编译(2)
- AngularJS Tutorial(12)from w3school
- 积累linux常用的命令