快速&准确的atan / arctan近似算法

时间:2017-03-01 17:13:59

标签: c algorithm function

任何快速&那里准确的atan / arctan近似函数/算法?输入:x =(0,1)(最小x要求)。输出:以弧度为单位

double FastArcTan(double x)
{
    return M_PI_4*x - x*(fabs(x) - 1)*(0.2447 + 0.0663*fabs(x));
}

我在网上找到了这个功能,但它的最大误差为1.6弧度,太大了。

1 个答案:

答案 0 :(得分:5)

OP报告的最大误差为1.6弧度(92度),这与测试下面的OP代码不一致,最大误差输入x:0到1范围约为0.0015弧度。我怀疑在0 ... 1范围之外的错误代码或测试。 OP意味着1.6毫弧度吗?

也许更准确的a*x^5 + b*x^3 + c*x对于OP来说仍然足够快。它在我的机器上平均精确度提高了4倍,最差情况提高了2倍。它使用@Foon@Matthew Pope

建议的最佳3项多项式
#include <math.h>
#include <stdio.h>

#ifndef M_PI_4
#define M_PI_4 (3.1415926535897932384626433832795/4.0)
#endif

double FastArcTan(double x) {
  return M_PI_4*x - x*(fabs(x) - 1)*(0.2447 + 0.0663*fabs(x));
}

#define A 0.0776509570923569
#define B -0.287434475393028
#define C (M_PI_4 - A - B)
#define FMT "% 16.8f"

double Fast2ArcTan(double x) {
  double xx = x * x;
  return ((A*xx + B)*xx + C)*x;
}

int main() {
  double mxe1 = 0, mxe2 = 0;
  double err1 = 0, err2 = 0;
  int n = 100;
  for (int i=-n;i<=n; i++) {
    double x = 1.0*i/n;
    double y = atan(x);
    double y_fast1 = FastArcTan(x);
    double y_fast2 = Fast2ArcTan(x);
    printf("%3d x:% .3f y:" FMT "y1:" FMT "y2:" FMT "\n", i, x, y, y_fast1, y_fast2);
    if (fabs(y_fast1 - y) > mxe1 ) mxe1  = fabs(y_fast1 - y);
    if (fabs(y_fast2 - y) > mxe2 ) mxe2  = fabs(y_fast2 - y);
    err1 += (y_fast1 - y)*(y_fast1 - y);
    err2 += (y_fast2 - y)*(y_fast2 - y);
  }
  printf("max error1: " FMT "sum sq1:" FMT "\n", mxe1, err1);
  printf("max error2: " FMT "sum sq2:" FMT "\n", mxe2, err2);
}

输出

 ...
 96 x: 0.960 y:      0.76499283y1:      0.76582280y2:      0.76438526
 97 x: 0.970 y:      0.77017091y1:      0.77082844y2:      0.76967407
 98 x: 0.980 y:      0.77529750y1:      0.77575981y2:      0.77493733
 99 x: 0.990 y:      0.78037308y1:      0.78061652y2:      0.78017777
100 x: 1.000 y:      0.78539816y1:      0.78539816y2:      0.78539816
max error1:       0.00150847sum sq1:      0.00023062
max error2:       0.00084283sum sq2:      0.00004826

不清楚为什么OP的代码使用fabs()给出&#34;输入:x =(0,1)&#34;。