我正在尝试为sin和cosine创建一个计算器,技术上只能在0-pi / 2的范围内运行。现在这可能看起来很愚蠢但后来会用到所以我可以使用泰勒系列。
我有一个主要工作的实现,但是当theta是x *(pi / 2)时,我有一个严重的问题,其中x是一个任意整数。看来,在这些价值观上,有时它们会被推入附近的象限,而这些象限并不属于他们。还有一些我偶然无法解释的直接错误。
如何才能提高效率和正确性呢?
以下是执行此操作的代码。
#define T_PI (2.0 * M_PI)
#define H_PI (0.5 * M_PI)
void sincos(float theta, float* cosine, float* cosine) {
int mode;
prepareForRange(&theta, cosine, sine);
Assert(!(f < 0.0 || f > H_PI));
*cosine = cos(theta);
*sine = sin(theta);
range_output(mode, cosine, sine);
}
void prepareForRange(float* theta, int* mode, float *cosine, float* sine) {
if (*theta < 0.0) *theta += ceil(-*theta / T_PI) * T_PI;
*mode = (int)floor(*theta / H_PI) % 4 + 1;
*theta = fmodf(*theta, H_PI);
}
void range_output(int mode, float *cos, float *sin) {
float temp;
switch (mode) {
case 1:
break;
case 2:
temp = *cos;
*cos = -*sin;
*sin = temp;
break;
case 3:
*cos = -*cos;
*sin = -*sin;
break;
case 4:
temp = *cos;
*cos = *sin;
*sin = -temp;
break;
default:
break;
}
}
答案 0 :(得分:1)
您正遇到一个名为range reduction的长期且常常无法识别的问题区域。基本问题是浮点PI常数仅定义为8位精度,因此当您尝试计算n~10 ^ 4的(x - n * PI)时,您的结果中的精度数字会丢失一半当n变大时更糟糕。这个问题没有简单的软件解决方案。为了在我自己的numerical library中真正解决它,我必须有效地实现任意精度浮点运算并存储一个320位(1078位)的PI常量。 libc的一些实现有效地为你做了这个,但不是全部,所以你不能安全地假设它。