fortran中的一致浮点运算与不同计算机上的不同编译器?

时间:2012-10-30 08:34:43

标签: math floating-point

如何使用不同的编译器以及可能还有不同的计算机使用浮点算法获得相同的结果?

这是p.f90

program fl
implicit none
real(kind=8) :: a

a=9d0/10d0
write(*,*) a

end program

使用gfortran -o p p.f90我得到0.90000000000000002

使用ifort -g -o p p.f90我得到0.900000000000000

有没有办法实现一致性? 小事物传播并变得更大。

祝你好运 的Alessandro

3 个答案:

答案 0 :(得分:8)

我们将在下面讨论浮点运算,但让我首先处理你的误解。在write语句中使用 list-directed格式意味着编译器选择写出变量的格式是编译器的选择;这不是语言标准的强制要求。您对*中的第二个write(*,*)的使用告诉编译器根据需要写出变量的值。所以你所拥有的并不是证明算术存在问题,而是gfortranifort之间存在差异。如果我将你的写声明修改为

write(*,'(f21.18)') a

然后我的英特尔Fortran程序写了

0.900000000000000022

到控制台。

由于不熟悉浮点运算的细节而产生的问题,所以我不打算写一篇论文,只是一些与你的问题相关的观察。

IEEE-754 64位浮点数(可能与声明real(kind=8)相同)仅提供大约16位有用信息的十进制数字。实际上,由于它们是二进制的,并且在一个基数和另一个基数中的数字之间没有简单的对应关系,它实际上是15.95个十进制数字,并且许多用户将这个数字向下舍入并且在浮动之后的第15个有效数字之后从不查看任何内容点数的十进制表示。因此,ifortgfortran都会误导您跟踪2

IEEE-754不仅定义了f-p数的格式,还定义了舍入和算术运算的一些规则。一个精心编写的程序只使用那些算术运算(我认为也指定了平方根)并且负责舍入模式和舍入运算应该在两个不同的处理器上产生相同的结果。当然,没有多少有用的数字程序仅限于基本的算术运算。

由于2003标准Fortran包含一个名为ieee_arithmetic的内部模块,它允许程序员直接访问运行它的硬件的基础IEEE-754功能 - 但请注意,它不需要硬件具有任何此类功能。使用ieee_arithmetic和另一个名为ieee_exceptions的内在模块,如果您的硬件提供必要的支持,您应该能够编写在gfortranifort下编译的程序,执行时,相同的结果到每个fp号的最后一位。

您还需要熟悉您正在使用的编译器的优化选项和数值算术选项。大多数编译器都有一个选项,其含义为sacrifice IEEE compliance for speed(对于ifort,我认为它是fp-model)。一般来说,遵守IEEE-754的操作会使你的程序变慢。

答案 1 :(得分:1)

答案 2 :(得分:0)

阿里:你做不到。

FORTRAN编译器的一个众所周知的问题是,结果无法与不同的编译器和体系结构进行比较。 不可能的主要原因与FORTRAN的设计决策有关 社区:计算机可能会更改执行顺序并使用内部计算机 专业优化速度。 由于浮点运算不是分布式的[x(y + z)!= xy + xz],结果是DOES 取决于执行顺序

e.g。

1E308(MAX)+(1E308 - 2E308)〜= 0E308

(1E308(MAX)+ 1E308) - 2E308 == INFINITY

你被困了。一些编译器使用例如融合乘法加法用于计算给出与“正常”不同结果的多项式,这是非常允许的。

你被困住了。遗憾。