我一直在谷歌上寻找解决这个问题的方法。我已经看到了许多方法来计算任何-1< = theta< = 1的atan(theta),但是当θ大于或小于那些边界时我不知道该怎么做。
我假设我需要加上或减去pi的倍数来抵消它?这种思路是否正确?
目前我有:
double my_atan(double x)
{
return x - (x*x*x)/3 + (x*x*x*x*x)/5;
}
对于以下代码,
int x;
for (x=0; x<M_PI*2; x++)
{
printf("Actual: %f\n", atan(x));
printf("Approx: %f\n", my_atan(x));
printf("\n");
}
它很快失去控制(如预期的那样,因为它超出了范围):
Actual: 0.000000
Approx: 0.000000
Actual: 0.785398
Approx: 0.866667
Actual: 1.107149
Approx: 5.733333
Actual: 1.249046
Approx: 42.600000
Actual: 1.325818
Approx: 187.466667
Actual: 1.373401
Approx: 588.333333
Actual: 1.405648
Approx: 1489.200000
此处未图示,但当θ在适当范围内时,输出相当准确。
所以我的问题是,究竟需要采取哪些步骤才能使my_tan函数支持更广泛的界限?
暂时盯着这一点,因此可以提供任何可以提供的指导
答案 0 :(得分:3)
让我完成你的例子并谈谈可能会有所帮助的一些事情:
#include <stdio.h>
#include <math.h>
double my_atan(double x)
{
return x - (x*x*x)/3 + (x*x*x*x*x)/5 - (x*x*x*x*x*x*x)/7;
}
int main()
{
double x;
for (x=0.0; x<M_PI*2; x+=0.1)
{
printf("x: %f\n", x);
printf("Actual: %f\n", atan(x));
printf("Approx: %f\n", my_atan(x));
printf("\n");
}
}
术语int x
是一个整数,您接近大角度。尝试在这里使用双打,你没有转换错误。
现在你的问题。你使用的泰勒系列只有你的| x |才有效&LT; 1。
泰勒系列越不准确,越远离某一点或你的情况为零(0 + x)。
该系列可以很好地运行到pi/4
,即使在那时它也是非常不准确的,但是更大的值会非常糟糕。所以对于较小的角度,它的效果非常好。
答案 1 :(得分:3)
我用于定点库的解是使用Remez algorithm的极小极大近似。即使在那里,我在三个范围内使用了一组不同的系数:0到0.5; 0.5到0.75和0.75到1.通过这种分解,我能够获得1 ULP的准确度。
然后你需要很好的参数减少来获得范围内的参数。在我的情况下,我使用了一个好的互惠函数来进行超过1的参数。以下是身份:
atan(-x) == -atan(x)
atan(x) == pi/2 - atan(1/x) // for x > 1
Taylor和Remez近似值nice blog post here;在该网站上也是Remez toolkit,用于查找所需的系数。