Я думаю, что для этого есть два разных подхода (* на самом деле, похоже, есть и «третий» подход, см. EDIT); один - использовать общую библиотеку, а другой - использовать синтаксический анализатор для математических выражений. Первый подход описан на странице Rossetastone (Call a function in a shared library) и странице SO (Fortran dynamic libraries, load at runtime?), например. Для второго подхода вы можете найти сторонние библиотеки, выполнив поиск с помощью «математического парсера» или «синтаксического анализатора 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
и tand
, но они не поддерживаются gfortran. Так, для компиляции, я заметил их и заменить их на stop
, т.е.
stop "sind not supported..."
! pdata(st) = sind(pdata(st))
(я предполагаю, что sind(x)
означает sin(x * pi/180)
, так что может быть в порядке, чтобы определить его как таковой.)
[EDIT]
«третий» подход А может вызвать встроенный eval()
функции в интерпретируемых языков, таких как Python или Джулии через system()
, например, this SO page. Хотя это также имеет множество слабых мест (и, вероятно, гораздо проще использовать такие языки напрямую), вызов eval()
из Fortran может быть полезен для определенных целей.
Вы имеете в виду во время компиляции или во время выполнения? Это две разные ситуации. –
Кодовый блок в начале вашего вопроса определенно совершенно неверен. Также 'kind = 8' очень уродливый и не переносимый. Это не означает 8 байтов во всех компиляторах. –
Существует такая вещь (http://stackoverflow.com/q/7326828), но это, возможно, не совсем то, что вы имеете в виду. – francescalus