问题描述
我正在寻找一种方法来读取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
语法可以提供帮助吗?
module util
use iso_fortran_env,only:dp => real64
隐式无
包含
子程序eval(expr,ans,x,y)
字符(*),intent(in):: expr
真实(dp),intent(out):: ans
real(dp),intent(in),可选项:: x,y
character(len(expr)+200)cmd,sx, sy
整数u
sx =;如果(present(y))write(sx,('x'',es25.15,';'))x
if sy,('y =',es25.15,';'))y
write(cmd,(a))&
python -cfrom __future__ import print_function,division;//&
from math import *;// trim(sx)// trim(sy)//&
print(eval('// trim(expr)//'))> tmp.dat
call system(trim(cmd))
打开(newunit = u,file =tmp.dat,status =old)
阅读(u,*)ans
关闭(u)
调用系统(rm -f tmp.dat)
结束子程序
结束模块
程序主体
使用util,仅: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推荐
$ ./a。 out
ans = 1001.4142135623731
ans = 200 3.1415926535899
ans = 12.000000000000000
,上面的代码通过system()在Python中调用内置的eval()函数。但是效率不高,因为结果值曾经写入到外部文件中(也是调用Python本身的开销)。所以如果效率很重要,最好使用更具体的第三方库,或者为了方便,直接使用解释型语言。 (如果计算过程不太苛刻,我建议采用后一种方法,因为它为编码节省了大量时间......)
Python:
from __future__导入print_function,除法
从数学导入*
str = input(输入表达式:)
x = 1.0
y = 2.0
print(eval(str))#如果在提示符中键入x + 10 * y,则会得到21
Julia:
println(输入表达式:)
$ p
str = readline()
x = 1.0
y = 2.0
println(eval(parse(str)))
$ b
如果可以使用
system()
并编写外部文件,另一个选项可能只需编写一个包含要评估表达式的小型Fortran代码,通过system()编译并运行它,通过外部文件得到结果。例如,如果我们替换上面代码中的两行(write(cmd,(a))...
和system(trim (cmd))
),它给出了相同的结果。这可能是有用的,如果我们想保持代码完全写在Fortran,用最小的修改努力。open(newunit = u,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)) (*,'(e30.20)')// trim(expr)
write(u,(a))end
close(u)
呼叫系统(gfortran -fdefault-real-8 -ffree-line-length-none tmp.f90&& ./a.out> tmp.dat)
!假设在Linux或Mac上使用bash(x86_64)。
! -fdefault-real-8被附加到8位浮点值来提升1.0等。
呼叫系统(rm -f tmp.f90)
I am looking for a way to read numerical expressions in Fortran.
With numerical expression I mean
dsqrt(0.5d0)/3.d0+1.d0
or something rather then the translated1.235...
real version.With reading I mean
open(unit=UnitNumber,file="FileName")read(UnitNumber, *) ....
I try to define in the reading statement the format, for instance
read(unitNumber,"(15F24.17)")
but it does not help. I amI am wondering if I can do it only internally, defining
real(8), parameter :: dsqrt(0.5d0)/3.d0+1.d0
.Maybe the use of
FORMAT
syntax could help?解决方案As suggested by @agentp, interpreted languages like Python and Julia can parse a string directly as a piece of code, so utilizing such a feature may be convenient for your purpose. But if you definitely need to achieve the same goal in Fortran, another approach (with least effort!) may be simply to call eval() in such languages, for example:
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
Results:
$ gfortran test.f90 # gfortran >=5 is recommended $ ./a.out ans = 1001.4142135623731 ans = 2003.1415926535899 ans = 12.000000000000000
More specifically, the above code simply invokes the built-in eval() function in Python via system(). But it is not very efficient because the resulting value is once written to an external file (and also the overhead to call Python itself). So if efficiency matters, it may be better to use more specific 3rd-party libraries, or for handiness, work with interpreted languages directly. (I suggest the latter approach if the calculation is not too demanding, because it saves much time for coding...)
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
Julia:
println( "Input an expression: " ) str = readline() x = 1.0 y = 2.0 println( eval( parse( str ) ) )
[ EDIT ]
If it is OK to use
system()
and write external files, another option may be to simply write a small Fortran code that contains the expression to be evaluated, compile and run it via system(), get the result via an external file. For example, if we replace the two lines in the above code (write( cmd, "(a)" ) ...
andsystem( trim( cmd ) )
) by the following, it gives the same result. This might be useful if we want to keep the code entirely written in Fortran, with minimal effort for modification.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" )
这篇关于I / O中的数值表达式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!