Floating point Fortran中正反函数的精度
以代码为例Floating point Fortran中正反函数的精度,floating-point,fortran,precision,gfortran,Floating Point,Fortran,Precision,Gfortran,以代码为例 PROGRAM TRIG_TEST IMPLICIT NONE DOUBLE PRECISION, PARAMETER :: PI=4.D0*DATAN(1.0D) print *, sin(PI/2.0), cos(PI/2.0) END PROGRAM TRIG_TEST 使用gfortran输出编译 1.0000000000000000 6.1232339957367660E-017 我知道常见的浮点问题,但是为什么sin函数等于1,而cos函数不等于零?让我们看看为
PROGRAM TRIG_TEST
IMPLICIT NONE
DOUBLE PRECISION, PARAMETER :: PI=4.D0*DATAN(1.0D)
print *, sin(PI/2.0), cos(PI/2.0)
END PROGRAM TRIG_TEST
使用gfortran
输出编译
1.0000000000000000 6.1232339957367660E-017
我知道常见的浮点问题,但是为什么
sin
函数等于1,而cos
函数不等于零?让我们看看为什么sin
的结果等于1。在代码中
DOUBLE PRECISION, PARAMETER :: PI=4.D0*DATAN(1.0D0)
这是pi值的浮点近似值。它可能非常接近真实值,但不是。此外,sin
函数在计算sin时也有错误。我们希望这些都是小错误
我们期望cos(pi/2)的值为零。您的浮点计算与数学答案的误差约为6.1232339957367660E-017
。让我们假设您的sin计算具有相似的误差大小
现在看看epsilon(0d)的值。这是1d0+ε(0d0)
不等于1d0
的最小数。在模型中,假设的误差比这个数字小得多(您报告的是“~2.2e-16”)
因此,1
是与浮点计算的实际值最接近的可表示数字
以该计划为例
use, intrinsic :: iso_fortran_env, only : real128, real64
implicit none
real(real64), parameter :: PI=4.D0*ATAN(1._real64)
real(real128), parameter :: PI_approx = PI ! Not 4*ATAN(1._real128)
print *, SIN(PI/2), COS(PI/2)
print *, SIN(PI_approx/2), COS(PI_approx/2)
end
这将(可能)计算PI/2的sin,但精度更高(使用与PI相同的近似值)。在第二种情况下,我的编译器报告的值不同于1
,但差异远小于epsilon(0.\u real64)
作为一个样式点,通常最好避免使用datan
,并使用genericatan
<代码>双精度
也可以由适当的种类参数代替。这些都显示在我上面的程序中。让我们看看为什么sin
的结果会给出1。在代码中
DOUBLE PRECISION, PARAMETER :: PI=4.D0*DATAN(1.0D0)
这是pi值的浮点近似值。它可能非常接近真实值,但不是。此外,sin
函数在计算sin时也有错误。我们希望这些都是小错误
我们期望cos(pi/2)的值为零。您的浮点计算与数学答案的误差约为6.1232339957367660E-017
。让我们假设您的sin计算具有相似的误差大小
现在看看epsilon(0d)的值。这是1d0+ε(0d0)
不等于1d0
的最小数。在模型中,假设的误差比这个数字小得多(您报告的是“~2.2e-16”)
因此,1
是与浮点计算的实际值最接近的可表示数字
以该计划为例
use, intrinsic :: iso_fortran_env, only : real128, real64
implicit none
real(real64), parameter :: PI=4.D0*ATAN(1._real64)
real(real128), parameter :: PI_approx = PI ! Not 4*ATAN(1._real128)
print *, SIN(PI/2), COS(PI/2)
print *, SIN(PI_approx/2), COS(PI_approx/2)
end
这将(可能)计算PI/2的sin,但精度更高(使用与PI相同的近似值)。在第二种情况下,我的编译器报告的值不同于1
,但差异远小于epsilon(0.\u real64)
作为一个样式点,通常最好避免使用datan
,并使用genericatan
<代码>双精度
也可以由适当的种类参数代替。这些都显示在我上面的程序中。以下假设double
是IEEE 754基本64位二进制格式。三角函数例程的常见实现不如格式要求的精确。但是,对于这个答案,让我们假设它们返回最准确的结果
π不能在double
中精确表示。最接近的可能值为884279719003555/281474976710656或3.14159265358979311599796346854418516159057671875。我们叫它p
p/2的正弦约为1− 1.8747•10−33两侧的double
中表示的两个值分别为1和0.999999999988897769797537484345957683319091796875,约为1− 1.11•10−16两者之间的距离越近为1,因此p/2
的最接近正弦的可表示值正好为1
p/2的余弦约为6.123233995736765886•10−17double
中可表示的最接近该值的值为6.123233995736766035868820147291983023128246062338790031898112806340349218957424163818359375•10−十七,
因此,您观察到的结果是最接近真实数学值的可能结果。以下假设
double
是IEEE 754基本64位二进制格式。三角函数例程的常见实现不如格式要求的精确。但是,对于这个答案,让我们假设它们返回最准确的结果
π不能在double
中精确表示。最接近的可能值为884279719003555/281474976710656或3.14159265358979311599796346854418516159057671875。我们叫它p
p/2的正弦约为1− 1.8747•10−33两侧的double
中表示的两个值分别为1和0.999999999988897769797537484345957683319091796875,约为1− 1.11•10−16两者之间的距离越近为1,因此p/2
的最接近正弦的可表示值正好为1
p/2的余弦约为6.123233995736765886•10−17double
中可表示的最接近该值的值为6.123233995736766035868820147291983023128246062338790031898112806340349218957424163818359375•10−十七,
因此,您观察到的结果是最接近真实数学值的可能结果。编译器的
epsilon(1d0)
值是多少?该值为~2.2e-16?听起来似乎合理。假设sin
和cos
都精确到7E-017
范围内。这就给出了cos
的答案1-7E-017
等于1.
[你说你理解“通常的浮动”