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
,并使用generic
atan
<代码>双精度
也可以由适当的种类参数代替。这些都显示在我上面的程序中。

让我们看看为什么
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
,并使用generic
atan
<代码>双精度
也可以由适当的种类参数代替。这些都显示在我上面的程序中。

以下假设
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−17
double
中可表示的最接近该值的值为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−17
double
中可表示的最接近该值的值为6.123233995736766035868820147291983023128246062338790031898112806340349218957424163818359375•10−十七,


因此,您观察到的结果是最接近真实数学值的可能结果。

编译器的
epsilon(1d0)
值是多少?该值为~2.2e-16?听起来似乎合理。假设
sin
cos
都精确到
7E-017
范围内。这就给出了
cos
的答案
1-7E-017
等于
1.
[你说你理解“通常的浮动”