流程圖:

程式碼:

  1. #include <stdint.h>
  2. double msqrt(double x)
  3. {//直式開方,適用 IEEE754 double
  4.     int i;
  5.     uint64_t r=0,k;
  6.     
  7.     //取得浮點數的s,e,f
  8.     uint32_t s=(*(uint64_t*)&x)>>63;
  9.     int32_t e=(*(uint64_t*)&x)>>52&0x7FF;
  10.     uint64_t f=(*(uint64_t*)&x)&0xFFFFFFFFFFFFFllu;
  11.     e-=1023;
  12.     
  13.     
  14.     if(e==1024)
  15.         return x;
  16.     if(e==-1023)
  17.     {
  18.         if(f==0)
  19.             return 0.0;
  20.         else
  21.         {
  22.             //正規化
  23.             while(!(f&0x10000000000000llu))
  24.             {
  25.                 f<<=1;
  26.                 --e;
  27.             }
  28.         }
  29.     }
  30.     if(s==1)
  31.     {
  32.         k=0xFFFFFFFFFFFFFFFF;
  33.         return *(double*)&k; //return NaN;
  34.     }
  35.     
  36.     //位值調整,並把e開根號
  37.     f=(e&1)?(f|0x10000000000000llu)<<1:(f|0x10000000000000llu);
  38.     e=(e>>1)|(e&0x80000000);
  39.     
  40.     //對f開根號
  41.     for(i=52;i>=0;i-=2)
  42.     {
  43.         k=(r<<2|1)<<i;
  44.         if(f>=k)
  45.         {
  46.             f-=k;
  47.             r=r<<1|1;
  48.         }
  49.         else
  50.             r<<=1;
  51.     }
  52.     for(i=0;i<26;++i)
  53.     {
  54.         f<<=2;
  55.         k=r<<2|1;
  56.         if(f>=k)
  57.         {
  58.             f-=k;
  59.             r=r<<1|1;
  60.         }
  61.         else
  62.             r<<=1;
  63.     }
  64.     //四捨五入
  65.     if( (f<<2) >= (r<<2|1) )
  66.         ++r;
  67.     
  68.     //e,f合併為double回傳
  69.     k=e+1023;
  70.     k=(r&0xFFFFFFFFFFFFFllu)|k<<52;
  71.     return *(double*)&k;
  72. }
文章標籤
全站熱搜
創作者介紹
創作者 ren1244 的頭像
ren1244

ren1244的部落格

ren1244 發表在 痞客邦 留言(0) 人氣(548)