Fortran学习笔记6(函数、子程序)
程序代码中,常常会在不同的地方重复用到某一功能和重复某一代码,这个时候就要使用函数。函数包括内嵌函数,自定义函数,子程序。
子程序Subroutine
子程序之所以叫子程序,是因为在没有经过调用之前,它不会被执行。(当然,如果把编译器对主函数的调用也看做同样的话则另当别论。)
包含子程序的程序的格式:
program main
......
......
call sub_1(...)
......
call sub_2(...)
......
end program main
subroutine sub_1(...)
...
end subroutine sub_1
subroutine sub_2(...)
...
end subroutine sub_2
主程序并不一定要放在最开始,它可以放在程序的任何地方(但是最好放在最开始或者结尾,如果你放在了一大段程序的中间……何苦为难自己!)子程序之间也可以互相调用。甚至可以自己调用自己,这个算法就叫递归,但是Fortran77不支持。调用语句为call。
有关子程序,一个很重要的概念是,子程序独立的拥有属于自己的变量申明。主程序和子程序,不同的子程序之间的变量名可以相同,他们互不干扰。除了变量独立,子程序还独立拥有自己的行代码。
在子程序的调用中会涉及到参数传递。Fortran中的参数传递使用的是传址调用。也就是说,实参和形参公用一块内存,两者改变其中之一,另一者也会发生变化,(其实是形参暂时的借住在实参家里。)
自定义函数Function
自定义函数的运行和上面的子程序没有什么两样,也需要调用才能被执行,也可以独立声明变量,参数传递的方法和子程序相同。尽管如此,自定义函数和子程序还是有两点不同:
- 调用自定义函数前要声明。
- 自定义函数调用后会返回一个数值。
下面是一个简单的程序:用牛顿法来解方程。
program main
implicit real*8(a-z)
external f,g
integer::max
integer::i,k=1
real*8::x0,x1,x2,dx,tol,f,g
open(unit=11,file='fin.txt')
open(unit=12,file='fout.txt')
read(11,*)x0,max,tol
do
x1=x0-f(x0)/g(x0)
dx=abs(x1-x0)
if(dx<=tol) exit
k=k+1
if(k>=max) exit
x0=x1
end do
write(12,*)x0
end program main
function f(x)
implicit none
real*8::f,x
f=x**3+2*x**2+10*x-20
end function
function g(x)
implicit none
real*8::g,x !,dx
g=3*x**2+4*x+10
end function
下面是一个更简单的例子:(摘自彭国伦《Fortran95程序设计》一书)
program main
implicit none
real::a=1,b
real add
add(a,b)=a+b
! 简单的子程序直接写在主程序里面,并且不用call调用。并且这样的函数只能在本主函数中使用,其他地方不能调用。
write(*,*)add(a,3.0)
stop
end program
写函数的时候请注意,尽量不要去改变传入的参数的数值,最好另开辟一个内存来存储要用的应变量,而不要随意去改变传入的自变量。
全局变量COMMON
不同的程序之间,也就是在不同的函数之间,除了可以通过传递参数的方法来共享内存,还可以通过全局变量来让不同程序中声明出来的变量使用相同的内存位置。
program main
implicit none
integer::a,b
common a,b
a=1
b=2
call sub()
end program
subroutine sub()
implicit none
integer::num1,num2
common num1,num2
write(*,*)num1,num2
return
end subroutine sub
由于全局变量使用的“地址对应”的方法在程序中共享数据,所以在程序设计时常常会出现一些不方便,比如在主程序中声明了6个全域变量,而你在子程序中只需要使用第六个全域变量,但是你不得不把前五个都写出来。这样很麻烦,一个幼小的解决办法是将全域变量分区。
program main
implicit none
integer::a,b,c,d
common/group1/ a,b
common/group2/ c,d
a=1
b=2
c=3
d=4
call sub_1()
call sub_2()
end program
subroutine sub_1()
implicit none
integer::num1,num2
common/group1/ num1,num2
write(*,*)num1,num2
return
end subroutine sub_1
subroutine sub_2()
implicit none
integer::num1,num2
common/group2/ num1,num2
write(*,*)num1,num2
return
end subroutine sub_2
BLOCK DATA
关于COMMON设置初值,不能直接在子程序或者主程序中使用data来设置初值,要在block data程序模块中使用data命令来设置初值。BLOCK data很像一段子程序,它也是一段独立的程序模块,也拥有自己的变量声明,不过它不需要别人调用就可以自己执行。事实上,这段程序会在主程序执行前生效,不过它的功能只在于设置全局变量的初值,不能有其他执行命令出现。具体语法如下:
block data name ! name可以省略
implicit none ! 最好不要省略
integer... ! 声明变量
real...
common ... ! 把变量放在公共空间
common/group1/... ! 公共空间分区
data var1,var2,...,varn/value1,value2,...,valuen/ ! data语句赋初值
...
...
end block data name ! 可以只写end或end block data
还有一点要注意,全局变量不能声明成常量。所以block data中不能出现parameter。
实际的例子如下:
program main
implicit none
integer::a,b
common a,b
integer::c,d
common/group1/c,d
integer::e,f
common/group2/e,f
write(*,*)a,b,c,d,e,f
stop
end program main
block data name ! name可以省略
implicit none ! 最好不要省略
integer::a,b
common a,b
data a,b/1,2/
integer::c,d
common/group1/ c,d
data c,d/3,4/
integer::e,f
common/group2/e,f
data e,f/5,6/
end block data name ! 可以只写end或end block data
小结
COMMON语法在数据共享式会出现很多限制和不足,建议不要使用而采用module语句来实现数据共享。
Fortran学习笔记6(函数、子程序)的更多相关文章
- Fortran学习笔记:01 基本格式与变量声明
Fortran学习笔记目录 01 基本格式与变量声明 格式 固定格式(Fixed Format):Fortran77 程序需要满足一种特定的格式要求,具体形式参考教材 自由格式(Free Format ...
- (目录)Fortran学习笔记:开坑!!!
前言:因为某些原因,需要使用Fortran编写程序,记录下Fortran语法学习过程中的部分笔记.在此开坑记录,立下Flag,"希望年末能够更新完" Fortran 学习笔记 陈橙 ...
- Matlab学习笔记 figure函数
Matlab学习笔记 figure函数 matlab中的 figure 命令,能够创建一个用来显示图形输出的一个窗口对象.每一个这样的窗口都有一些属性,例如窗口的尺寸.位置,等等.下面一一介绍它们. ...
- matlab学习笔记 bsxfun函数
matlab学习笔记 bsxfun函数 最近总是遇到 bsxfun这个函数,前几次因为无关紧要只是大概看了一下函数体去对比结果,今天再一次遇见了这个函数,想想还是有必要掌握的,遂查了些资料总结如下. ...
- Fortran学习笔记4(循环语句)
Fortran学习笔记4 Fortran学习笔记4 逻辑运算 循环 Do语句 Do-While循环 循环控制 循环应用实例 逻辑运算 if命令需要和逻辑运算表达式搭配才能起到很好的效果.下面分别列出F ...
- matlab学习笔记13_1 函数返回值
一起来学matlab-matlab学习笔记13函数 13_1 函数返回值 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考文献 https://blog.csdn.net/qq_36556 ...
- Fortran学习笔记:03 数组(Array)
Fortran学习笔记目录 书接上回:Fortran学习笔记:02 流控制语句 数组(Array) 定义数组 一维数组 program main implicit none integer :: i ...
- Fortran学习笔记:02 流控制语句
Fortran学习笔记目录 书接上回:Fortran学习笔记:01 基本格式与变量声明 流控制语句 IF语句 IF (逻辑表达式) THEN ... ELSE ... END IF SELECT-CA ...
- swift学习笔记2——函数、闭包
之前学习swift时的个人笔记,根据github:the-swift-programming-language-in-chinese学习.总结,将重要的内容提取,加以理解后整理为学习笔记,方便以后查询 ...
- haskell学习笔记_函数
一开始学习函数式编程语言就被告知函数式编程语言是一种“定义式”的语言,而不是一种命令式的语言,在学习haskell的函数语法时,此感觉更加强烈,haskell的函数定义倾向于一种类似C++里面的swi ...
随机推荐
- Ajax登陆,使用Spring Security缓存跳转到登陆前的链接
Spring Security缓存的应用之登陆后跳转到登录前源地址 什么意思? 用户访问网站,打开了一个链接:(origin url)起源链接 请求发送给服务器,服务器判断用户请求了受保护的资源. 由 ...
- [SDOI2019] 热闹又尴尬的聚会
热闹度\(p\)子图中最小的度数,尴尬度\(q\)独立集大小,之间的约束 \[ \begin{aligned} \lfloor n/(p+1)\rfloor\le q &\rightarrow ...
- Elasticsearch学习记录(入门篇)
Elasticsearch学习记录(入门篇) 1. Elasticsearch的请求与结果 请求结构 curl -X<VERB> '<PROTOCOL>://<HOST& ...
- (八)SpringBoot使用mybatis-plus+自动代码生成
一.SpringBoot使用mybatis-plus+自动代码生成 使用mybatis-plus可以自动帮我们生成通用的 controller,service,dao,mapper 二.加入依赖 &l ...
- struts2与struts1的比较
struts2相对于struts1来说简单了很多,并且功能强大了很多,我们可以从几个方面来看: 从体系结构来看:struts2大量使用拦截器来出来请求,从而允许与业务逻辑控制器 与 servlet-a ...
- 最短路之SPFA(单源)HDU 2066
#include "iostream" #include "cstdio" #include "queue" #include <cs ...
- BZOJ1415(期望dp)
解法: 首先bfs预处理go数组:可可在j点时聪聪在点i是怎样贪心走的,这是为了之后O(1)获取转移线路. 然后dfs记忆化一下f[i][j],代表从i到j的期望,对于每层:将所有情况的期望值相加.边 ...
- Codeforces 1132D(二分模拟)
要点 二分显然,关键在于怎么判断 题解方法:开k个队列代表每个时间有哪些电脑会挂掉,这部分O(n)预处理一下,之后扫一遍时间,每个时间点贪心选取最靠前的会挂的电脑未雨绸缪给它充电,然后看看充电以后要不 ...
- DDX和DDV——控件与变量之间值的传递
DoDataExchange由框架调用,作用是交互并且验证对话框数据,主要由(DDX) 和 (DDV)宏实现. 永远不要直接调用这个函数,而是通过UpdateData(TRUE/FALSE)实现控件与 ...
- mysql 定时任务和存储过程
mysql 定时任务和存储过程 最近在做日志系统,中间用到了 mysql, 其中有一个要求: 把数据库中 7天之后的日志清除了.看到 mysql 也支持 定时任务.于是就用 mysql 来做了.下面就 ...