信天游 发表于 2012-12-2 16:34:05

献上一个在小区间上的反三角函数的快速算法

本帖最后由 信天游 于 2012-12-2 16:36 编辑

C51的函数库中带有反三角函数acos(x),但是对于速度要求高的场合,库函数的速度有点不理想,想再快一点的话就要自己构造函数来代替库函数,新手今天为献上一个快速算法,以及是怎样得到的(这种近似方法只适用于小区间的计算)
在纸上画出y=arccos(x)的图像,取x在(根号3/2,1)区间上,y在(0,π/6)区间上,在此区间上原函数的图象可近似看做是一段抛物线,通过待定系数法可以求出抛物线的方程为y=√((-2.083)(x-1)),到此就完成了第一步近似实际值是[π²/(36((√3)/2)-1)]
再来看y=√((-2.083)(x-1)),还要用到库函数中的开方运算,小弟我又上网找了找,找到了一种计算方法,叫做Carmack快速开放算法,坛子里有关于这个算法的介绍(搜索“神一样的算法”),将Carmack算法稍微做一下修改就是开放算法
但是将两种算法结合在一起,回产生较大的误差,这时候可以适当的减小y=√((-2.038)(x-1))中的系数,可以取-2.045,这时候的误差小于0.1%,一般均可以适应实际的计算要求
以下是算法代码:float arccos(float arc)
{
         float x=(-2.045)*(arc-1);
         float xhalf = 0.5f*x;
//      float xhalf = 0.5f*x;
         float buf=x;
         long i = *(long*)&x;
//注:使编译器强制将x按照 long int 型变量处理
      i = 0x5f3759df - (i >> 1);//What the fuck ???
         x = *(float*)&i;
         x = x*(1.5f - xhalf*x*x);      //1次迭代
//       x = x*(1.5f - xhalf*x*x);      //2次迭代
      return (x*buf);
       
}小弟新手,欢迎拍砖,别拍脸{:biggrin:}

kevinstar888 发表于 2012-12-2 16:38:20

{:sweat:} 怎么这么眼熟啊,这代码。特别是那句注释what the fuck?

信天游 发表于 2012-12-2 16:40:29

kevinstar888 发表于 2012-12-2 16:38 static/image/common/back.gif
怎么这么眼熟啊,这代码。特别是那句注释what the fuck?

代码本身就是基于Carmack快速开放算法的

error_dan 发表于 2012-12-2 16:48:32

又见幻数。。。。
页: [1]
查看完整版本: 献上一个在小区间上的反三角函数的快速算法