【发布时间】:2018-04-29 00:17:26
【问题描述】:
我正在尝试创建一个在技术上仅在 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;
}
}
【问题讨论】:
-
当您发布这样的问题时,您应该包括至少一个输入案例,它不会产生所需的结果,以及您从代码中获得的结果和您期望的结果。该代码可能存在浮点舍入问题。浮点数并不精确地表示实数。特别是,
M_PI不能正好是 π,并且使用M_PI的倍数会使偏差成倍增加。请参阅 the answers to this question 以获取有关正确算法的线索。 -
我的方法是使用类似的归约,但涉及有理数:
k = prepareForRange(int x2)。那么您的函数 sincos(x) 将采用sincos(k*pi)的形式,其中k是三角简化分数。
标签: c math trigonometry