[轉]純C實現sqrt,cos,sin,atan2
阿新 • • 發佈:2019-01-23
一開始的想法就是cos,sin,atan2都可以使用泰勒級數,sqrt可以使用牛頓法。
然後。。。上網找資料。。。
首先是SQRT,這位仁兄基本思路和我一樣,但是他在最後提供的這段程式碼的確很神奇。列在下面。
[cpp] view plain copy print?- float Sqrt(float x)
- {
- float xhalf = 0.5f*x;
- int i = *(int*)&x;
- i = 0x5f375a86 - (i >> 1);
- x = *(float*)&i;
- x = x*(1.5f - xhalf*x*x);
- x = x*(1.5f - xhalf*x*x);
- x = x*(1.5f - xhalf*x*x);
- return 1 / x;
- }
而後是COS和SIN,也是用泰勒級數,但是程式有點問題,我做了小小修正:
[cpp] view plain copy print?- float Sin(float x)
- {
- int sign = 1;
- int itemCnt = 4;
- int k = 0;
- float result = 0.0f;
- float tx = 0.0f;
- int factorial = 1;
- if(x < 0)
- {
- x = -x;
- sign *= -1;
- }
- while(x >= SL_2PI)
- {
- x -= SL_2PI;
- }
- if(x > SL_PI)
- {
- x -= SL_PI;
- sign *= -1;
- }
- if(x > SL_PI_DIV_2)
- {
- x = SL_PI - x;
- }
- tx = x;
- for (k = 0; k < itemCnt; k ++)
- {
- if(k%2 == 0)
- {
- result += (tx / factorial);
- }
- else
- {
- result -= (tx / factorial);
- }
- tx *= (x * x);
- factorial *= (2*(k+1));
- factorial *= (2*(k+1) + 1);
- }
- if (1 == sign)
- return result;
- else
- return -result;
- }
atan2有點麻煩,因為sin和cos的級數收斂很快(分母為(2n+1)!和(2n)!),而atan不一樣,分母為2n+1。WIKI上面有一個更加有效率的公式:
但是感覺收斂效果仍舊一般,所以最終選擇了積分式,程式碼如下:
[cpp] view plain copy print?- float Atan2(float y, float x, int infNum)
- {
- int i;
- float z = y / x, sum = 0.0f,temp;
- float del = z / infNum;
- for (i = 0; i < infNum;i++)
- {
- z = i*del;
- temp = 1 / (z*z + 1) * del;
- sum += temp;
- }
- if (x>0)
- {
- return sum;
- }
- elseif (y >= 0 && x < 0)
- {
- return sum + PI;
- }
- elseif (y < 0 && x < 0)
- {
- return sum - PI;
- }
- elseif (y > 0 && x == 0)
- {
- return PI / 2;
- }
- elseif (y < 0 && x == 0)
- {
- return -1 * PI / 2;
- }
- else
- {
- return 0;
- }
- }
這個方法雖然誤差已經很小了,至少不影響我計算方向場,但是應該還有更好的。至少我在stackoverflow裡面看到的是如此。比如有如此開原始碼,蘋果的。
http://blog.csdn.net/simitwsnyx/article/details/45890281