Getting double precision in fortran 90 using intel

2019-02-24 18:46发布

I have a very large code that sets up and iteratively solves a system of non-linear partial differential equation, written in fortran. I need all variables to be double precision. In the additional module that I have written for the code, I declare all variables as the double precision type, but my module still uses variables from the old source code that are declared as type real. So my question is, what happens when a single-precision variable is multiplied by a double precision variable in fortran? Is the result double precision if the variable used to store the value is declared as double precision? And what if a double precision value is multiplied by a constant without the "D0" at the end? Can I just set a compiler option in Intel 11.1 to make all real/double precision/constants of double precision?

4条回答
贪生不怕死
2楼-- · 2019-02-24 19:15

So my question is, what happens when a single-precision variable is multiplied by a double precision variable in fortran? The single precision is promote to double precision and the operation is done in double precision.

Is the result double precision if the variable used to store the value is declared as double precision? Not necessarily. The right-hand side is an expression that doesn't "know" about the precision of the variable on the left hand side, in to which it will be stored. If you have Double = SingleA * SingleB (using names to indicate the types), the calculation will be performed in single precision, then converted to double for storage. This will NOT gain extra precision for the calculation!

And what if a double precision value is multiplied by a constant without the "D0" at the end? This is just like the first question, the constant will be promoted to double precision and the calculation done in double precision. However, the constant is still single precision and even if you wrote down many digits as for a double-precision constant, the internal storage is single precision and cannot represent that accuracy. For example, DoubleVar * 3.14159265359 will be calculated in double precision, but will be something approximating DoubleVar * 3.14159 done in double precision.

If you want to have the compiler retain many digits in a constant, you must specific the precision of a constant. The Fortran 90 way to do this is to define your own real type with whatever precision that you need, e.g., to require at least 14 decimal digits:

integer, parameter :: DoubleReal_K = selected_real_kind (14)
real (DoubleReal_K) :: A
A = 5.0_DoubleReal_K
A = A * 3.14159265359_DoubleReal_K
查看更多
爷、活的狠高调
3楼-- · 2019-02-24 19:27

Jonathan Dursi's answer is correct - the other part of your question was if there was a way to make all real variables double precision.

You can accomplish this with the ifort compiler by using the -i8 (for integers) and -r8 (for reals) options. I'm not sure if there is a way to force the compiler to interpret literals as double-precision without specifying them as such (e.g. by changing 3.14159265359 to 3.14159265359D0) - we ran into this issue a while back.

查看更多
我欲成王,谁敢阻挡
4楼-- · 2019-02-24 19:28

If you write numbers in the form 0.1D0 it will treat it as double precision number, otherwise if you write 0.1, the precision will be lost in the conversion. Here is an example:

program main
implicit none
real(8) a,b,c
a=0.2D0
b=0.2
c=0.1*a
print *,a,b,c
end program

When compiled with

ifort main.f90

I get results:

0.200000000000000       0.200000002980232       2.000000029802322E-002

When compiled with

ifort -r8 main.f90

I get results:

0.200000000000000       0.200000000000000       2.000000000000000E-002

If you use the IBM XLF compiler, the equivalence is

xlf -qautodbl=dbl4 main.f90
查看更多
再贱就再见
5楼-- · 2019-02-24 19:31

The Fortran standard is very specific about this; other languages are like this, too, and it's really what you'd expect. If an expression contains an operation on two floating-point variables of different precisions, then the expression is of the type of the higher-precision operand. eg,

(real variable) + (double variable) -> (double)

(double variable)*(real variable) -> (double)

(double variable)*(real constant) -> (double)

etc.

Now, if you are storing the result in a lower-precision floating point variable, it'll get down-converted again. But if you are storing it in a variable of the higher precision, it'll maintain it's precision.

If there's any cases where you're concerned that a single-precision floating point variable is causing a problem, you can force it to be converted to double precision using the DBLE() intrinsic:

DBLE(real variable) -> double

查看更多
登录 后发表回答