首页 > 解决方案 > Fortran 中的乘法使用 ifort 和 gfortran 给出不同的结果

问题描述

我有一个在 Linux 上使用 gfortran-9 编译的程序,或者在 Windows 上使用 ifort 编译的程序。Windows 编译是一种我没有太多访问权限的黑匣子。

无论如何,在某些时候,两个代码都必须进行相同的乘法运算,但结果在小数点后 13 位是不同的。

这是我为在我的 Linux 机器上测试这个乘法而编写的测试代码:

      implicit none
      double precision:: a,b,c,d
 200  format(F35.20)
      b=20.17865682672815452747d0
      c=3.75000000000000000000d0
      d=32.17399999999999948841d0
      a=b*c*d
      write(*,200)a
      end program

在带有 gfortran 的 Linux 上,我有 2434.60539278681835639873 值。在具有 ifort 的 Windows 上,执行相同的乘法并给出 2434.60539278681881114608 。两者都使用 -O2 选项编译。

我想不出它不同的原因。是因为双精度不能更精确,我应该移到real(16)?

感谢您的见解。

标签: floating-pointfortrangfortranintel-fortran

解决方案


有 3 种不同的方式可以对乘法进行排序。Gfortran 和 ifort 恰好选择了不同的顺序。使用括号你可以看到发生了什么:

ian@eris:~/work/stack$ cat mult.f90
implicit none
      double precision:: a,b,c,d
 200  format(F35.20)
      b=20.17865682672815452747d0
      c=3.75000000000000000000d0
      d=32.17399999999999948841d0
      a=(b*c)*d
      write(*,200)a
      b=20.17865682672815452747d0
      c=3.75000000000000000000d0
      d=32.17399999999999948841d0
      a=b*(c*d)
      write(*,200)a
      b=20.17865682672815452747d0
      c=3.75000000000000000000d0
      d=32.17399999999999948841d0
      a=c*(b*d)
      write(*,200)a
      end program
ian@eris:~/work/stack$ gfortran --version
GNU Fortran (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

ian@eris:~/work/stack$ gfortran -O2 mult.f90
ian@eris:~/work/stack$ ./a.out
          2434.60539278681835639873
          2434.60539278681881114608
          2434.60539278681881114608

这两个答案都是完全正确的——你只是看到了浮点数学的一种效果。


推荐阅读