I / O中的数值表达式

时间:2016-11-26 20:38:42

标签: io fortran

我正在寻找一种在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语法可能会有所帮助吗?

3 个答案:

答案 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中不一定太多)。

我根本不清楚为什么你想要这个,你打算如何使用这样的表达。它必须是某种特定的类型,你需要特定的子程序来评估这样的表达式。