我正在寻找一种在Fortran中读取数值表达式的方法。
使用数字表达式,我的意思是dsqrt(0.5d0)/3.d0+1.d0
或者更确切地说是翻译后的1.235...
实际版本。
阅读我的意思是
open(unit=UnitNumber,file="FileName")
read(UnitNumber, *) ....
我尝试在阅读语句中定义格式,例如read(unitNumber,"(15F24.17)")
,但它没有帮助。我是
我想知道我是否只能在内部进行,定义real(8), parameter :: dsqrt(0.5d0)/3.d0+1.d0
。
使用FORMAT
语法可能会有所帮助吗?
答案 0 :(得分:1)
正如@agentp所建议的那样,像Python和Julia这样的解释语言可以直接将字符串解析为一段代码,因此利用这样的功能可能对您的目的很方便。但是如果你肯定需要在Fortran中实现相同的目标,另一种方法(尽量少付!)可能只是在这些语言中调用eval(),例如:
module util
use iso_fortran_env, only: dp => real64
implicit none
contains
subroutine eval( expr, ans, x, y )
character(*), intent(in) :: expr
real(dp), intent(out) :: ans
real(dp), intent(in), optional :: x, y
character(len(expr)+200) cmd, sx, sy
integer u
sx = "" ; sy = ""
if ( present(x) ) write( sx, "(' x = ', es25.15, ' ; ')" ) x
if ( present(y) ) write( sy, "(' y = ', es25.15, ' ; ')" ) y
write( cmd, "(a)" ) &
"python -c ""from __future__ import print_function, division ; " // &
"from math import * ; " // trim(sx) // trim(sy) // &
"print( eval( '" // trim(expr) // "' ))"" > tmp.dat"
call system( trim( cmd ) )
open( newunit=u, file="tmp.dat", status="old" )
read( u, * ) ans
close( u )
call system( "rm -f tmp.dat" )
end subroutine
end module
program main
use util, only: dp, eval
implicit none
character(200) str
real(dp) ans
str = "sqrt( 2.0 ) + 1000.0"
call eval( str, ans )
print *, "ans = ", ans
str = "acos( x ) + 2000.0"
call eval( str, ans, x= -1.0_dp )
print *, "ans = ", ans
str = "10 * x + y"
call eval( str, ans, x= 1.0_dp, y= 2.0_dp )
print *, "ans = ", ans
end program
结果:
$ gfortran test.f90 # gfortran >=5 is recommended
$ ./a.out
ans = 1001.4142135623731
ans = 2003.1415926535899
ans = 12.000000000000000
更具体地说,上面的代码只是通过system()在Python中调用内置的eval()函数。但它效率不高,因为结果值一旦写入外部文件(以及调用Python本身的开销)。因此,如果效率很重要,最好使用更具体的第三方库,或者为了便利,直接使用解释语言。 (如果计算不是太苛刻,我建议使用后一种方法,因为它可以节省很多编码时间......)
的Python:
from __future__ import print_function, division
from math import *
str = input( "Input an expression: " )
x = 1.0
y = 2.0
print( eval( str ) ) # if you type "x + 10 * y" in the prompt, you get 21
朱莉娅:
println( "Input an expression: " )
str = readline()
x = 1.0
y = 2.0
println( eval( parse( str ) ) )
[编辑]
如果可以使用system()
并编写外部文件,另一个选项可能是简单地编写一个包含待评估表达式的小型Fortran代码,通过system()编译并运行它,得到结果通过外部文件。例如,如果我们通过以下代码替换上述代码中的两行(write( cmd, "(a)" ) ...
和system( trim( cmd ) )
),则会得到相同的结果。如果我们希望保持代码完全用Fortran编写,那么这可能很有用,只需要很少的修改工作。
open( newunit=u, file="tmp.f90" )
write( u, "(a)" ) "implicit none"
write( u, "(a)" ) "real :: x, y"
write( u, "(a)" ) trim(sx)
write( u, "(a)" ) trim(sy)
write( u, "(a)" ) "write(*,'(e30.20)') " // trim(expr)
write( u, "(a)" ) "end"
close( u )
call system( "gfortran -fdefault-real-8 -ffree-line-length-none tmp.f90 && ./a.out > tmp.dat" )
! Assuming bash on Linux or Mac (x86_64).
! -fdefault-real-8 is attached to promote 1.0 etc to 8-byte floating-point values.
call system( "rm -f tmp.f90" )
答案 1 :(得分:1)
对于记录,库fparser允许您精确地执行您的要求:在Fortran中将字符串计算为数学表达式,而无需任何其他编程语言。
答案 2 :(得分:0)
不,在Fortran或任何相关的编程语言中都没有这样的内容。有类似用途的特定库(在Fortran中不一定太多)。
我根本不清楚为什么你想要这个,你打算如何使用这样的表达。它必须是某种特定的类型,你需要特定的子程序来评估这样的表达式。