使用 intel 11.1 编译器在 fortran 90 中获取双精度
我有一个非常大的代码,用于建立并迭代求解非线性偏微分方程组,用 Fortran 编写。我需要所有变量都是双精度的。在我为代码编写的附加模块中,我将所有变量声明为双精度类型,但我的模块仍然使用旧源代码中声明为 real 类型的变量。所以我的问题是,当单精度变量乘以 Fortran 中的双精度变量时会发生什么?如果用于存储值的变量声明为双精度,结果是否为双精度?如果双精度值乘以末尾没有“D0”的常数会怎样?我可以在 Intel 11.1 中设置一个编译器选项来使所有实数/双精度/双精度常数吗?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
所以我的问题是,在 fortran 中,当单精度变量乘以双精度变量时会发生什么? 单精度提升为双精度,并且运算以双精度完成。
如果用于存储值的变量声明为双精度,结果是否为双精度? 不一定。右侧是一个表达式,它不“知道”左侧变量的精度,该变量将存储在左侧。如果Double = SingleA * SingleB(使用名称来指示类型),将以单精度进行计算,然后转换为double进行存储。这不会获得额外的计算精度!
如果一个双精度值乘以一个末尾没有“D0”的常量会怎样?这就像第一个问题一样,常量将提升为双精度,并以双精度进行计算精确。 但是,该常量仍然是单精度的,即使你像双精度常量一样写下了很多位,内部存储也是单精度的,无法代表该精度。例如,DoubleVar * 3.14159265359 将以双精度计算,但将以双精度计算近似于 DoubleVar * 3.14159。
如果希望编译器在常量中保留许多数字,则必须指定常量的精度。 Fortran 90 的方法是根据您需要的任何精度来定义您自己的实际类型,例如,需要至少 14 位十进制数字:
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:
Fortran 标准对此非常具体;其他语言也是如此,这确实是您所期望的。如果表达式包含对两个不同精度的浮点变量的运算,则该表达式属于更高精度操作数的类型。例如,
(实数变量)+(双精度变量)-> (双精度)
(双精度变量)*(实数变量) -> (双精度)
(双精度变量)*(实常数) -> (double)
等。
现在,如果您将结果存储在较低精度的浮点变量中,它将再次向下转换。但如果您将其存储在精度更高的变量中,它将保持其精度。
如果在任何情况下您担心单精度浮点变量导致问题,您可以强制将其转换为双精度
使用 DBLE() 内在函数:
DBLE(实数变量) ->双倍的
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
如果您以 0.1D0 的形式写入数字,它会将其视为双精度数字,否则如果您写入 0.1,则会在转换中丢失精度。
下面是一个示例:
当用 I 编译时,
我得到结果:
当用 I 编译时
,我得到结果:
如果您使用 IBM XLF 编译器,则等价的是
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:
When compiled with
I get results:
When compiled with
I get results:
If you use the IBM XLF compiler, the equivalence is
Jonathan Dursi 的回答 是正确的 - 你问题的另一部分是是否有办法使所有实数变量双精度。
您可以通过 ifort 编译器使用
-i8
(对于整数)和-r8
(对于实数)选项来完成此操作。我不确定是否有办法强制编译器将文字解释为双精度而不指定它们(例如,通过将 3.14159265359 更改为 3.14159265359D0) - 我们不久前遇到了这个问题。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.