我认为有两种不同的方法(*事实上,似乎还有“第三种”方法,请参阅编辑);一种是使用共享库,另一种是使用数学表达式的解析器。 Rossetastone 页面中描述了第一种方法(调用共享库中的函数)和一个 SO 页面(Fortran动态库,在运行时加载?), 例如。对于第二种方法,您可以通过搜索“数学解析器”或“Fortran数学解析器”等来找到第三方库。在这里,我尝试过this one因为它看起来很简单(只有一个模块并且无需安装)。如果我们编写一个像这样的简单测试程序
program test
use interpreter, only: init, evaluate, dp => realkind
implicit none
integer, parameter :: mxvars = 10 !! consider 10 variables at most here
character(10) :: symbols( mxvars )
real(dp) :: values( mxvars ), answer
character(1000) :: funcstr !! a user-defined math expression
character(5) :: stat
!> Define variable names.
symbols( 1 ) = "x"
symbols( 2 ) = "a"
symbols( 3 ) = "b"
symbols( 4 ) = "c"
symbols( 5 ) = "foo"
!> Get a math expression.
print *, "Please input a math expression:"
read(*, "(a)") funcstr !! e.g., a * x + b
!> Init the evaluator.
call init( funcstr, symbols, stat )
if ( stat /= "ok" ) stop "stat /= ok"
!> Set values for the variables.
values( : ) = 0
values( 1 ) = 2.0_dp ! x
values( 2 ) = 10.0_dp ! a
values( 3 ) = 7.0_dp ! b
!> Evaluate.
answer = evaluate( values )
print *, "function value = ", answer
end program
并将其编译为(*1)
$ gfortran -ffree-line-length-none interpreter.f90 mytest.f90
我们可以测试各种表达式如下:
$ ./a.out
Please input a math expression:
a * x + b
function value = 27.000000000000000
$ ./a.out
Please input a math expression:
sin( a * x ) + cos( b ) + foo
function value = 1.6668475050709324
其他库的用法看起来也很相似。由于每个库的性能可能有很大差异,因此尝试几个不同的库进行比较可能会很有用。
(*1) 该模块有一些行sind
, cosd
, and tand
,但 gfortran 不支持它们。因此,为了编译,我将它们注释掉并替换为stop
, i.e.,
stop "sind not supported..."
! pdata(st) = sind(pdata(st))
(我猜sind(x)
means sin( x * pi / 180 )
,所以这样定义可能就可以了。)
[EDIT]
“第三种”方法可能是调用内置的eval()
在 Python 或 Julia 等解释语言中使用函数system()
, e.g., 这个页面。尽管这也有很多弱点(并且直接使用此类语言可能更容易),但调用eval()
Fortran 语言可能对某些特定目的有用。