昨天学了subroutine,咋说呢,没啥感觉,出现了一个问题就是,我发现子程序没法自己调用自己,就是没法子形成递归。今天学习函数,看看Fortran的函数可不可以像c++等编程语言那样可以进行递归操作。
应该是可以的,因为Fortran的自定义函数有这么两个特点:
1、调用之前要先声明;
2、自定义函数会返回一个数值
在Fortran中,函数的声明要写external,表示这不是一个变量,而是一个可以调用的函数,虽然这个词可以被省略掉,但是还是不要省略的好。
举个简单的例子,自定义函数进行两数相乘:
function prod(a,b)
implicit none
integer::a,b
integer ::prod
!prod和函数名相同,并不是用来声明变量,而是声明这个函数会返回的类型
prod=a*b
return
end
program main
implicit none
integer ::a,b
integer,external::prod
write(*,*)"two number"
read(*,*)a,b
write(*,*)prod(a,b)
stop "over"
end
function的声明是这样的(最简单等方法就是在vscode上写个fun然后tab键,就可以看到啦!)
datatype function name(input) result(output)
argument type, intent(inout) :: input
function type :: output
end function name
一旦有了datatype function function_name之后,就可以不用像第一段代码中用 integer::prod声明,function不需要用call来调用,非常方便,有他自身的优点。
那么,在不同函数之间呢,尤其是主函数和函数之间,我们除了可以传递参数来共享内存以外,还可以通过全局变量来让不同程序中声明的变量使用相同的内存位置。
Fortran中全局变量是用common来声明的,但注意,common声明的全局变量不能随便的用data来赋值,取全局变量的时候,会根据他们声明的相对位置关系来对应,而非使用变量来对应,就像下面的例子,num1对应 的就是a,num2对应的就是b,Fortran一个很难受的地方就是,全局变量是使用地址对应的方法在程序中共享数据:
subroutine ShowCommon()
implicit none
integer::a,b
common a,b
write(*,"(I3,I3)")a,b
! return
stop
end
program main
implicit none
integer::num1,num2
common num1,num2
num1=2
num2=3
call ShowCommon()
stop "over"
end
其实是可以把变量归类,放在独立的common区间里面:
common变量值不能够直接在子程序或主程序中用data来设置初值,要在BLOCK DATA模块中使用data命令来设置初值。
block data name!name可以省略的
implicit none
integer...!声明变量
real...
common ...!把变量方法佛common空
common /group1/...
data var1,var2...!同样使用data来设定初始值
...
end block data
program example
implicit none
integer::a,b
common a,b
integer::c,d
integer::e,f
common/group1/c,d
common/group2/e,f
write(*,"(6I4)")a,b,c,d,e,f
stop "over"
end
block data
implicit none
integer a,b
common a,b
integer c,d
data a,b/1,2/
common/group1/c,d
data c,d/3,4/
integer::e,f
common/group2/e,f
data e,f/5,6/
end
之前留的问题解决了,Fortran传递参数时候,传递的是这个变量的内存地址,就是c++的取地址&
好家伙,Fortran的数组传递和c++也是一样的,传入的是数组第一个元素的内存地址,即&array(1)
之后你的操作和传入参数大同小异,直接就是再函数中声明一下数组,之后对数组操作就行,那么就做一个斐波那契数列:
function fibnoacci(arr)
implicit none
integer(kind=4)::arr(10)
integer::fibnoacci
integer i
arr(1)=0
arr(2)=1
do i=3,10
arr(i)=arr(i-1)+arr(i-2)
end do
return
end
program main
implicit none
integer,external:: fibnoacci
integer(kind=4)::arr(10)
! external::fibnoacci
fibnoacci(arr)
write(*,"(I3,I3,I3,I3,I3,I3,I5,I5,I5,I5)")arr
stop "fibnoacci over"
end program
!我用自定义函数做,就会在主程序调用函数的时候出现一个错误:
!Error: Unclassifiable statement at (1)百思不得其解呀
最后用子函数实现了
subroutine fibnoacci(a)
implicit none
integer::a(10)
integer i
a(1)=0
a(2)=1
do i=3,10
a(i)=a(i-1)+a(i-2)
end do
return
end
!在主程序里面加个call就行
okok,今天就到这里吧,吃饭去了,晚上在思考思考最后一个到底错在了哪里,如果有想法的话,我在之后的博客里会写的。