C++泰勒公式实现反余弦函数

    手动实现反三角函数这些其实很多情况下是没有意义的,因为这些都是封装好的!可是就在发表这篇文章的前几天,就有人让我帮他实现,很多搞硬件的都会遇到这种情况………这个其实很容易,我用迈克劳林公式实现之后,突然又有点不明白,比如我们要求acos(0.6)的值,按照泰勒公式应该是求acos在0.6的n阶导数,怎么能只用acos在0处的n阶导数直接求得?直到几天后的今天我才想明白。

泰勒公式是这样的:


其中的高阶无穷小。其中迈克劳林公式是a为0时的特殊情况。如果仅仅是从这里来理解的话,确实,只有x趋向于a的时候,泰勒公式才能达到任意的精度。否则无穷小就无从谈起了。

但是,其实只是一种定性的描述,他被称为佩亚诺余项,我们充其量只能得出:当x趋向于a时,余项可以无穷小。但是却无法知道,当x不趋向与a时,余项是不是依然能足够小,这个条件是不充分的,为此,我们还需要定量的描述余项,来研究它的性质。


不过至少在发这篇文章的时候,百度百科和维基百科上的泰勒中值定理的介绍全是错的,实际上那是拉格朗日余项。真正的泰勒中值定理是更普适性的,像拉格朗日余项,柯西余项……都是它的特殊情况!

下面我们用拉格朗日余项来研究:

其实当时(这里ξ是x0与x之间的某个值),此余项就是拉格朗日余项,他之所以重要,是因为这里的x不需要趋向x0,因为它可以由柯西中值定理证得,而柯西中值定理实际上对区间两个端点距离是不做任何要求的!

于是我们可以看到只要n足够大,拉格朗日余项会趋向无穷小①,所以当我们只在0处展开泰勒公式求一个函数的近似值时,只要展开项数足够多,依然可以达到任意精度!

实际上我们看到,泰勒公式的精度可以用两种方式达到:x与x0的间距足够小或者是展开项数足够多。

以上是理论证明,但是它的实现却很简单,可以查一下反三角函数acos的泰勒展开:

 
  
arccos x = π/2 - ( x + 1/2*x^3/3 + 1*3/(2*4)*x^5/5 + …… ) (|x|<1) 

然后用C实现:

float aacos(float x){
    unsigned char i;
    float ans=x,t1=1,t2=x;x*=x;
    for(i=3;i<51;i+=2){
        t1*=(float)(i-2)/(float)(i-1);
        t2*=x;
        ans+=(t1*t2/(float)i);
    }
    return ans=1.5708-ans;
}
可以用C的封装好的acos()函数测试一下:

#include 
#include 
float aacos(float x){
    unsigned char i;
    float ans=x,t1=1,t2=x;x*=x;
    for(i=3;i<51;i+=2){
        t1*=(float)(i-2)/(float)(i-1);
        t2*=x;
        ans+=(t1*t2/(float)i);
    }
    return ans=1.5708-ans;
}
int main(){
    float ang;
    while(scanf("%f",&ang)!=EOF)
        printf("%.5f   %.5f\n",aacos(ang),acos(ang));
    return 0;
}
可以发现任意输入一个数,几乎结果时一模一样的,而这里我们只展开了前50项。

之所以用float型以及为何如此紧凑,是因为当一个人真正面对不得不手打一些数学函数的时候,一般是不会有double型的,而且能用char就尽量用char!

同样,我们还可以实现sqrt()函数,log()函数以及一些其他的数学函数。

ps:

其实①的论证还不严谨,它也只是看起来像无穷小而已,要想真正达到无穷小,必须说明分子是有上界的,而我还不能说明,不过当我发现的时候,我会重新修改!

你可能感兴趣的:(算法)