C 什么;“误差中的不连续性”;在这个三角参数化简中是否存在?

C 什么;“误差中的不连续性”;在这个三角参数化简中是否存在?,c,c99,C,C99,我一直在阅读,在那里我发现了这段神秘的摘录(重点是我的): 7.12.4三角函数 实现说明:应使用三角参数缩减 通过一种不会导致系统灾难性不连续的方法执行 计算结果的错误。特别是,仅基于 关于类计算的朴素应用 x-(2*pi)*(int)(x/(2*pi)) 是不明智的。 这个缩减公式到底有什么问题?根据周期性的性质,它看起来很好,2*piπ的间隔是一个无理数,不能用一个有限的浮点值来精确表示,这都是有理数 各种实现都支持一个常数,比如M_PI,它几乎是π,但不完全是π。所以下面介绍了错误。当然

我一直在阅读,在那里我发现了这段神秘的摘录(重点是我的):

7.12.4三角函数 实现说明:应使用三角参数缩减 通过一种不会导致系统灾难性不连续的方法执行 计算结果的错误。特别是,仅基于 关于类计算的朴素应用

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)
)”的方法。