三角变元约化(约化模2π;)
我正在尝试创建一个计算正弦和余弦的计算器,从技术上讲,它只能在0-pi/2的范围内运行。现在这可能看起来很愚蠢,但稍后将使用它,以便我可以使用泰勒级数 我有一个主要工作的实现,但是当θ是x*(pi/2)的形式时,我有一个严重的问题,其中x是一个任意整数。看起来,在这些值上,有时它们会被推到不属于它们的邻近象限中。还有一些我无法解释的偶然的直接错误 我怎样才能使它更加有效和正确 下面是执行此操作的代码三角变元约化(约化模2π;),c,math,trigonometry,C,Math,Trigonometry,我正在尝试创建一个计算正弦和余弦的计算器,从技术上讲,它只能在0-pi/2的范围内运行。现在这可能看起来很愚蠢,但稍后将使用它,以便我可以使用泰勒级数 我有一个主要工作的实现,但是当θ是x*(pi/2)的形式时,我有一个严重的问题,其中x是一个任意整数。看起来,在这些值上,有时它们会被推到不属于它们的邻近象限中。还有一些我无法解释的偶然的直接错误 我怎样才能使它更加有效和正确 下面是执行此操作的代码 #define T_PI (2.0 * M_PI) #define H_PI (0.5 * M_
#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;
}
}
#定义T#PI(2.0*M#PI)
#定义H_PI(0.5*M_PI)
空正弦(浮点θ、浮点*余弦、浮点*余弦){
int模式;
准备安排(&θ、余弦、正弦);
断言(!(f<0.0|f>H|PI));
*余弦=余弦(θ);
*正弦=正弦(θ);
量程输出(模式、余弦、正弦);
}
无效准备安排(浮点*θ、整数*模式、浮点*余弦、浮点*正弦){
如果(*θ<0.0)*θ+=ceil(-*θ/T_π)*T_π;
*模式=(内部)楼层(*θ/H_π)%4+1;
*θ=fmodf(*θ,H_-PI);
}
无效范围_输出(整数模式、浮点*cos、浮点*sin){
浮子温度;
开关(模式){
案例1:
打破
案例2:
温度=*cos;
*cos=-*sin;
*sin=温度;
打破
案例3:
*cos=-*cos;
*sin=-*sin;
打破
案例4:
温度=*cos;
*cos=*sin;
*sin=-temp;
打破
违约:
打破
}
}
您遇到了一个长期存在且经常无法识别的问题领域,名为。基本问题是,浮点PI常数的定义精度仅为8位,因此,当您试图计算n~10^4的(x-n*PI)时,结果中的精度已经降低了一半,并且随着n的增大,精度会变得更差。这个问题没有简单的软件解决方案。为了真正解决这个问题,我必须有效地实现任意精度浮点运算,并存储一个320位(1078位)的PI常量。libc的一些实现可以有效地为您做到这一点,但不是全部,因此您不能安全地假设它。当您发布这样的问题时,您应该至少包括一个输入案例,它不能产生所需的结果,以及您从代码中获得的结果和预期的结果。代码可能存在浮点舍入问题。浮点数不能精确地表示实数。特别是,M_PI
不能精确为π,使用M_PI
的倍数将使偏差成倍增加。有关正确算法的详细信息,请参阅。我的方法是使用类似的约简,但涉及有理数:k=prepareForRange(int x2)
。那么你的函数sincos(x)的形式是sincos(k*pi)
其中k
是三角约化分数。浮点pi常数仅定义为8位精度
你从哪里得到的?OP声明了一个double
M_-PI,精度约为15-17位,在变量和参数中只能转换为float
。无论如何,如果精度为8,则单个精度浮点只有~7位数字。请注意@LưuVĩnhPhúc:我同意你所有的挑剔。当然,这些都不是问题的核心,这就是他的PI和使用它的算术运算远没有达到缩小范围所需的精度。