我正在用gfortran和ifort编译一个简单的fortran程序:
! acos.f90
function real8_to_int8(real8) result(int8)
real(8), intent (in) :: real8
integer(8) :: int8
int8 = transfer(real8, int8)
end function
function int8_to_real8(int8) result(real8)
integer(8), intent (in) :: int8
real(8) :: real8
real8 = transfer(int8, real8)
end function
program main
integer(8) :: real8_to_int8
real(8) :: int8_to_real8
real :: x, acos_x
x = int8_to_real8(4605852290655121993)
print *, " size of x: ", sizeof(x)
write (*, '(A, F65.60)') ' x: ', x
print *, ""
acos_x = acos(x)
write (*, '(A, F65.60)') ' acos(x): ', acos(x)
print *, "bits: ", real8_to_int8(acos_x)
print *, ""
print *, ""
end program
为了尽可能精确地比较结果,我打印出变量的位表示,它们是不同的:
ifort:
$ ifort -real-size 64 -o acos_ifort acos.f90; ./acos_ifort
size of x: 8
x: 0.852326110783516388558211929193930700421000000000000000000000
acos(x): 0.550379481046229246388179490168113261461000000000000000000000
bits: 4603132597196780746
gfortran:
$ gfortran -fdefault-integer-8 -fdefault-real-8 -o acos_gfortran acos.f90; ./acos_gfortran
size of x: 8
x: 0.852326110783516388558211929193930700421333312988281250000000
acos(x): 0.550379481046229357410481952683767303824424743652343750000000
bits: 4603132597196780747
变量acos(x)
的差异是正常的吗?或者如何更改gfortran编译选项,使gfortran的结果与ifortran相同?
ifort:
acos(x): 0.550379481046229246388179490168113261461000000000000000000000
bits: 4603132597196780746
gfortran:
acos(x): 0.550379481046229357410481952683767303824424743652343750000000
bits: 4603132597196780747
发布于 2022-11-28 22:56:56
是的,angle
的差别是正常的。一般情况下,不能假设不同的三角函数实现才能产生精确的结果。从整数表示中可以看出,这两个值之间只有1 ulp差,这是完全合理的。
编辑并作为标准-一致性和样式问题,下面是您的代码的一个版本
kind=8
.
iso_fortran_env
内置模块的int64
和real64
,而不是非便携的,这些函数作为包含的过程来获得显式的接口检查(虽然在这种情况下,它有点没有意义,因为我们可以直接调用transfer
,但是只是为了演示包含的procedures).-fdefault-real-8
和类似的选项。)! acos.f90
program main
use iso_fortran_env
real(real64) :: x, acos_x
x = int8_to_real8(4605852290655121993_int64)
print *, " size of x: ", sizeof(x)
write (*, '(A, F65.60)') ' x: ', x
print *, ""
acos_x = acos(x)
write (*, '(A, F65.60)') ' acos(x): ', acos(x)
print *, "bits: ", real8_to_int8(acos_x)
print *, ""
print *, ""
contains
function real8_to_int8(real8) result(int8)
real(real64), intent (in) :: real8
integer(int64) :: int8
int8 = transfer(real8, int8)
end function
function int8_to_real8(int8) result(real8)
integer(int64), intent (in) :: int8
real(real64) :: real8
real8 = transfer(int8, real8)
end function
end program
https://stackoverflow.com/questions/74608336
复制