Io I/O中的数值表达式
我正在寻找一种用Fortran阅读数字表达式的方法 用数字表示,我指的是Io I/O中的数值表达式,io,fortran,Io,Fortran,我正在寻找一种用Fortran阅读数字表达式的方法 用数字表示,我指的是dsqrt(0.5d0)/3.d0+1.d0或其他什么,而不是翻译后的1.235…真实版本 我是说读书 open(unit=UnitNumber,file=“FileName”) 读取(单元号,*).. 我试图在reading语句中定义格式,例如read(unitNumber,“(15F24.17)”),但它没有帮助。我是 我想知道我是否只能在内部定义real(8),参数::dsqrt(0.5d0)/3.d0+1.d0 也许
dsqrt(0.5d0)/3.d0+1.d0
或其他什么,而不是翻译后的1.235…
真实版本
我是说读书
open(unit=UnitNumber,file=“FileName”)
读取(单元号,*)..
我试图在reading语句中定义格式,例如read(unitNumber,“(15F24.17)”)
,但它没有帮助。我是
我想知道我是否只能在内部定义real(8),参数::dsqrt(0.5d0)/3.d0+1.d0
也许使用
格式
语法会有所帮助?不,在Fortran或任何相关编程语言中都没有类似的东西。有用于类似目的的特定库(在Fortran中不一定太多)
我一点也不清楚你为什么要这样做,以及你打算如何使用这样的表达方式。它必须是某种特定的类型,并且您需要特定的子例程来计算这样的表达式。不,在Fortran或任何相关编程语言中都没有类似的东西。有用于类似目的的特定库(在Fortran中不一定太多)
我一点也不清楚你为什么要这样做,以及你打算如何使用这样的表达方式。它必须是某种特定的类型,并且您需要特定的子例程来计算这样的表达式。正如@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" )
正如@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" )
对于记录,该库允许您精确地执行您要求的操作:在Fortran中作为数学表达式计算字符串,而不需要任何其他编程语言。对于记录,该库允许您精确地执行您要求的操作:在Fortran中作为数学表达式计算字符串,不需要任何其他编程语言。几天前有类似的问题。我会做出同样的评论,为什么是fortran?解释语言(例如python)可以很容易地做这些事情。@agentp因为它是更复杂程序的开始部分。也许你是对的,我可以从Fortran内部调用像Octave、python等。。。。我将在几天前考虑类似的问题。我会做出同样的评论,为什么是fortran?解释语言(例如python)可以很容易地做这些事情。@agentp因为它是更复杂程序的开始部分。也许你是对的,我可以从Fortran内部调用像Octave、python等。。。。我将把行中的itRead看作一个ascii字符串,然后自己解析它。您将需要解析()/-+***和=。还有DSIN、SQRT等。使用反向波兰符号(RPN)可能是最简单的方法。@Holmz:正如我在回答中提到的,这样的解析器已经以。的形式存在。将行作为ascii字符串读入,然后自己解析。您将需要解析()/-+***和=。还有DSIN、SQRT等。使用反向波兰符号(RPN)可能是最简单的方法。@Holmz:正如我在回答中提到的,这样的解析器已经存在了