C 什么;“误差中的不连续性”;在这个三角参数化简中是否存在?
我一直在阅读,在那里我发现了这段神秘的摘录(重点是我的): 7.12.4三角函数 实现说明:应使用三角参数缩减 通过一种不会导致系统灾难性不连续的方法执行 计算结果的错误。特别是,仅基于 关于类计算的朴素应用C 什么;“误差中的不连续性”;在这个三角参数化简中是否存在?,c,c99,C,C99,我一直在阅读,在那里我发现了这段神秘的摘录(重点是我的): 7.12.4三角函数 实现说明:应使用三角参数缩减 通过一种不会导致系统灾难性不连续的方法执行 计算结果的错误。特别是,仅基于 关于类计算的朴素应用 x-(2*pi)*(int)(x/(2*pi)) 是不明智的。 这个缩减公式到底有什么问题?根据周期性的性质,它看起来很好,2*piπ的间隔是一个无理数,不能用一个有限的浮点值来精确表示,这都是有理数 各种实现都支持一个常数,比如M_PI,它几乎是π,但不完全是π。所以下面介绍了错误。当然
x-(2*pi)*(int)(x/(2*pi))
是不明智的。
这个缩减公式到底有什么问题?根据周期性的性质,它看起来很好,
2*pi
π的间隔是一个无理数,不能用一个有限的浮点值来精确表示,这都是有理数
各种实现都支持一个常数,比如M_PI
,它几乎是π,但不完全是π。所以下面介绍了错误。当然,如果(x/(2*pi)
超出int
范围,这是一个问题
double pi = M_PI;
double x; // radians
double y; // reduced radians.
y = x - (2*pi) * (int)(x/(2*pi))
如果此错误对代码很重要,则是特定于应用程序的。典型问题是tan(x)
,其中x
接近π*(n+1/2),并且x
上的微小变化将生成+或-无穷大/DBL_MAX
一些平台提供π归约函数
关于这个问题的一个很好的参考是K.C.Ng和SunPro FP小组的成员
要降低程度:
度的范围缩小为
fmod(x,360.0)
可以将x
精确地减少到-360.0
的范围内。最好使用remquo
:一方面,随着x的增加,情况会越来越糟,因为对于任何可表示的浮点值pi
@Grzegorz-Szpetkowski注意到y=fmod(x,2*mpi);
肯定比y=x-(2*PI)*(int)(x/(2*PI))
好。如果这足够好的话,是特定于应用的。嗯,我注意到x-(2*PI)*(int)(x/(2*PI))
还对接近2*π倍数的值引入了大的抵消。mpi
的不精确性,乘法(由于其舍入误差)以及对几乎相同的有效位进行减法相消会使剩余的位失去意义。对于具有不连续性的接近2*π()倍数的触发函数,这是有问题的。决定使用sin(x)作为其基本基元,而不是sin(2πx)和1-cos(2πx)这意味着程序无法精确计算上述函数的精确表示值x。我想知道有多少非人为的情况出现,在这种情况下,对精度感兴趣的代码应该计算弧度测量角度大于π/2的三角函数?即使要计算例如sin(x/1000000)[即,一个周期为2000000π]的函数要求在进行除法之前对x进行参数缩减(这当然……意味着它是在进行调用之前进行的)。我怀疑,计算sin(x)的代码通常是刚刚将x乘以π的倍数,代码真正想要计算的是sin的数学值(x*π/roundedPi)。我知道弧度在微积分中很有用,但在大多数其他应用中,精确表示的圆分数更有用。@supercat听起来像是sin2pi(转数)
等将是sin(弧度)
在您描述的情况下的好伴侣。就像log(x)
有伴侣:log10(x),log2()
。详细说明了反制“程序无法精确计算上述函数(如sin(x)
)”的方法。