記錄幾個開平方演算法

來源:互聯網
上載者:User

整數開平方演算法:

本演算法只採用移位、加減法、判斷和迴圈實現,因為它不需要浮點運算,也不需要乘除運算,因此可以很方便地運用到各種晶片上去。

我們先來看看10進位下是如何手工計算開方的。
先看下面兩個算式,
x = 10*p + q  (1)
公式(1)左右平方之後得:
x^2 = 100*p^2 + 20pq + q^2 (2)
現在假設我們知道x^2和p,希望求出q來,求出了q也就求出了x^2的開方x了。
我們把公式(2)改寫為如下格式:
q = (x^2 - 100*p^2)/(20*p+q) (3)
這個算式左右都有q,因此無法直接計算出q來,因此手工的開方演算法和手工除法演算法一樣有一步需要猜值。

我們來一個手工計算的例子:計算1234567890的開方

首先我們把這個數兩位兩位一組分開,計算出最高位為3。也就是(3)中的p,最下面一行的334為餘數,也就是公式(3)中的(x^2 - 100*p^2)近似值

       3
    ---------------
    | 12 34 56 78 90
       9
    ---------------
    |  3 34
下面我們要找到一個0-9的數q使它最接近滿足公式(3)。我們先把p乘以20寫在334左邊:

       3  q
    ---------------
    | 12 34 56 78 90
       9
    ---------------
  6q|  3 34
我們看到q為5時(60+q*q)的值最接近334,而且不超過334。於是我們得到:

       3  5
    ---------------
    | 12 34 56 78 90
       9
    ---------------
  65|  3 34
    |  3 25
    ---------------
          9 56
接下來就是重複上面的步驟了,這裡就不再囉嗦了。 

這個手工演算法其實和10進位關係不大,因此我們可以很容易的把它改為二進位,改為二進位之後,公式(3)就變成了:

q = (x^2 - 4*p^2)/(4*p+q) (4)
我們來看一個例子,計算100(二進位1100100)的開方:

      1  0  1  0
    ---------------
    | 1 10 01 00
      1
    ---------------
 100| 0 10 
    | 0 00 
    ---------------
    |   10 01
1001|   10 01
    ---------------
            0 00
這裡每一步不再是把p乘以20了,而是把p乘以4,也就是把p右移兩位,而由於q的值只能為0或者1,所以我們只需要判斷餘數(x^2 - 4*p^2)和(4*p+1)的大小關係,如果餘數大於等於(4*p+q)那麼該上一個1,否則該上一個0。

下面給出完成的C語言程式,其中root表示p,rem表示每步計算之後的餘數,divisor表示(4*p+1),通過a>>30取a的最高2位,通過a<<=2將計算後的最高2位剔除。其中root的兩次<<1相當於4*p。程式完全是按照手工計算改寫的,應該不難理解。

unsigned short sqrt(unsigned long a){
  unsigned long rem = 0;
  unsigned long root = 0;
  unsigned long divisor = 0;
  for(int i=0; i<16; i++){
    root <<= 1;
    rem = ((rem << 2) + (a >> 30));
    a <<= 2;
    divisor = (root<<1) + 1;
    if(divisor <= rem){
      rem -= divisor;
      root++;
    }
  }
  return (unsigned short)(root);
}


基於二分法的開平方演算法

#include <stdio.h>
//求絕對值
#define abs(x) (x)>0?(x):(-(x))
 
int  main(){
    double val;
    double eps;
    //value及精度
    printf("Input $value $eps->");
    scanf("%lf %lf",&val,&eps);
    if(val < 0 )
    {
        val*=-1;
    }
    double low,high;
    if(val  < 1)
    {
        low = val;
        high = 1;
    }
    else
    {
        low= 1;
        high = val;
    }
    while(1)
    {
        double mid =  (high + low)/2;
        double tmp =  mid * mid;
        if((abs(tmp-val))< eps)
        {
            printf("%f\n",mid);
            break;
        }
        if(tmp > val)
        {
            high = mid;
        }
        else
       {
            low = mid;
        }
    }
}


神秘的0x5f3759df之卡馬克的開平方演算法

float kamake_sqr(float number) {     

    long i;     
    float x, y;     
    const float f = 1.5F;     
    x = number * 0.5F;     
    y = number;     
    i = *(long *) &y;     
    i = 0x5f3759df - (i >> 1);     
    y = *(float *) &i;     
    y = y * (f - (x * y * y));     
    y = y * (f - (x * y * y));     
    return number * y;     
}     
    
main() {     
    printf("sqr(100)=%f", kamake_sqr(100.0));     
    getch();     
}   


輸出:sqr(100)=9.999964

演算法裡面求平方根一般採用的是無限逼近的方法,比如牛頓迭代法,

比如求5的平方根,選一個猜測值比如2,那麼我們可以這麼算
5/2 = 2.5; 2.5+2/2 = 2.25; 5/2.25 = xxx; 2.25+xxx/2 = xxxx ...

這樣反覆迭代下去,結果必定收斂於sqrt(5)

卡馬克牛就牛在選擇了0x5f3759df 這個開始值,使得迭代的時候收斂速度暴漲,對於Quake III所要求的精度10的負三次方,只需要一次迭代就能夠得到結果。

附加一個小故事:

普渡大學的數學家Chris Lomont看了以後覺得有趣,決定要研究一下卡馬克弄出來的這個猜測值有什麼奧秘。Lomont也是個牛人,在精心研究之後從理論上也推匯出一個最佳猜測值,和卡馬克的數字非常接近, 0x5f37642f。卡馬克真牛,他是外星人嗎?

傳奇並沒有在這裡結束。Lomont計算出結果以後非常滿意,於是拿自己計算出的起始值和卡馬克的神秘數字做比賽,看看誰的數字能夠更快更精確的求得平方根。結果是卡馬克贏了... 誰也不知道卡馬克是怎麼找到這個數位。

最後Lomont怒了,採用暴力方法一個數字一個數字試過來,終於找到一個比卡馬克數字要好上那麼一丁點的數字,雖然實際上這兩個數字所產生的結果非常近似,這個暴力得出的數字是0x5f375a86。



聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.