如何确保gfortran与ifort编译器复杂函数输出精度一致?
问题描述
使用cf.f90代码计算复函数值并输出,分别通过gfortran -O3 -o cf.exe cf.f90和ifort -O3 cf.f90 -o cf.exe编译后,发现gfortran输出16位小数精度的结果,ifort仅保留14位,二者输出存在差异;在更大规模的代码中,gfortran的结果符合预期,但ifort不符合。需要解决如何让ifort达到与gfortran相同的精度。
代码示例
program complex_func IMPLICIT NONE integer, parameter :: dp = selected_real_kind(15, 307) Real(dp) x complex(dp) CF x = 0.7 call complex_example(x, CF) end program complex_func Subroutine complex_example(y, my_CF) Implicit None integer, parameter :: dp = selected_real_kind(15, 307) Real(dp) y Complex(dp) my_CF, my_CF2, val(3), sumval(3) complex(dp), parameter :: I = (0.0_dp, 1.0_dp) ! sqrt(-1) my_CF = (I+1) * exp(I*y) / y val = [my_CF, my_CF, (0.0_dp, 0.0_dp)] write(*,*) 'adding complex array :' sumval = val + val write(*,*) sumval return end Subroutine complex_example
gfortran输出
adding complex array : (0.34464148256663812,4.0258854202296295) (0.34464148256663812,4.0258854202296295) (0.0000000000000000,0.0000000000000000)
ifort输出
adding complex array : (0.344641482566638,4.02588542022963) (0.344641482566638,4.02588542022963) (0.0000000000000000,0.0000000000000000)
解决方法
1. 显式指定输出格式(推荐)
问题核心是两个编译器对双精度复数的默认输出格式不同:gfortran默认输出16位小数,ifort默认仅输出14位。直接在write语句中指定格式字符串,强制输出足够精度即可统一结果。
将原代码中的write(*,*) sumval修改为:
write(*,'(3("(",F18.16,",",F18.16,") "))') sumval
如果需要科学计数法格式,也可以用:
write(*,'(3("(",ES23.16,",",ES23.16,") "))') sumval
修改后,两个编译器的输出精度会完全一致。
2. 调整ifort编译选项保证计算精度
如果大规模代码中计算过程也存在精度差异(而非仅输出),可以添加ifort编译选项限制浮点优化的激进程度,确保计算行为与gfortran对齐:
ifort -O3 -fp-model precise cf.f90 -o cf.exe
-fp-model precise会禁用一些可能降低精度的优化(比如浮点表达式收缩),让计算结果更接近严格的双精度计算标准。
3. 统一实数类型定义(可选)
虽然selected_real_kind(15, 307)在两个编译器中都对应64位双精度,但直接使用标准的double precision类型定义可以避免潜在的类型匹配问题:
! 替换原有的dp定义 double precision :: x complex(double precision) :: CF, my_CF, my_CF2, val(3), sumval(3) complex(double precision), parameter :: I = (0.0d0, 1.0d0)
内容的提问来源于stack exchange,提问作者ZeroTwo
相关产品推荐
相关产品推荐

