1. 程式人生 > >不用SQRT開平方的C++程式碼

不用SQRT開平方的C++程式碼

定義  求一個數a的平方根的運算,叫做開平方(extraction of square root),其中a叫做被開方數。   a必須大於或等於零,即a為非負數   開方公式   X(n + 1) = Xn + (A / Xn – Xn)1 / 2.。(n,n+1與是下角標)   開平方的理論依據   開平方是平方的逆運算,只要我們知道平方的計算方法,開平方就迎刃而解了。   我們令10位數值為A,個位數值為B,即為A*10+B,根據二數和的平方有:   (A*10+B)^2=(A*10)^2+2(A*10)*B+B^2=(A^2)*100+(20A+B)*B。   舉例說明:例359^2計算方法   1、3^2=9,   2、(20*3+5)*5=325,   3、(20*35+9)*9=6381,   4、將這些數,按兩位分節合起來:90000+32500+6381=128881。得359^2=128881。   將這些計算步驟倒過來,就是開平方。同理,可以得開立方及N次方的方法。

編輯本段
開方的計算步驟

  1.將被開方數的整數部分從個位起向左每隔兩位劃為一段,用撇號分開(豎式中的11’56),分成幾段,表示所求平方根是幾位數; 筆算開平方方法

筆算開平方方法

  2.根據左邊第一段裡的數,求得平方根的最高位上的數(豎式中的3);   3.從第一段的數減去最高位上數的平方,在它們的差的右邊寫上第二段陣列成第一個餘數(豎式中的256);   4.把求得的最高位數乘以20去試除第一個餘數,所得的最大整數作為試商(20×3除256,所得的最大整數是 4,即試商是4);   例項 開方公式   X(n + 1) = Xn + ( Xn – Xn)1 / 2.。(n,n+1與是下角標)   例如,A=5:   5介於2的平方至3的平方;之間。我們取初始值2.1,2.2,2.3,2.4,2.5,2.6,2.7,2.8,2.9都可以,我們最好取 中間值2.5。   第一步:2.5+(5/2.5-2.5)1/2=22;輸入值大於輸出值,負反饋;   即5/2.5=2,2-2.5=-0.5,-0.5×1/2=-0.25,2.5+(-0.25)=2.25,取2位數2.2。
  第二步:2.2+(5/2.2-2.2)1/2=2.23;輸入值小於輸出值,正反饋;   即5/2.2=2.27272,2.27272-2.2=0.07272,0.07272×1/2=0.03636,2.2+0.03636=2.23636。取3位數2.23。   第三步:2.23+(5/2.23-2.23)1/2=2.236。   即5/2.23=2.2421525,,2.2421525-2.23=0.0121525,,0.0121525×1/2=0.00607,,2.23+0.006=2.236.,取4位數。   每一步多取一位數。這個方法又叫反饋開方,即使你輸入一個錯誤的數值,也沒有關係,輸出值會自動調節,接近準確值。   例如A=200.   200介如10的平方---20的平方之間。初始值可以取11,12,13,14,15,16,17,18,19。我們去15.   15+(200/15-15)1/2=14。取19也一樣得出14.。:19+(200/19-19)1/2=14.。   14+(200/14-14)1/2=14.1。

  14.1+(200/14.1-14.1)1/2=14.14.

//為了取第一個靠近值,網上學習的一個開方整數的函式

//該函式能算出目標值的整數位,在此用來計算我們要取的第一個目標值
unsigned long sqrt_16(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 root;//(unsigned short)(root);
}


float sqrt_new(float m)
{
 unsigned long s=0;
 float t=0.0;
 
 if (m>=1.00)
 {
  s=sqrt_16(unsigned long(m));
  t=s+(m/s-s)/2;
 }
 else {
  t=float(0.4);
  t=t+(m/t-t)/2;  //牛頓切線法  
  t=t+(m/t-t)/2;  //次數越多,精度越高
  t=t+(m/t-t)/2;  
  t=t+(m/t-t)/2;  //精確可以在0.0001開方
 }
// t=t+(m/t-t)/2;
 t=t+(m/t-t)/2;
 t=t+(m/t-t)/2;
 return t;
}


void main()
{
 while(1)
 {
  float x;
  cout<<"Please input a num:";
  cin>>x;
  cout<<sqrt_new(x)<<endl;
  cout<<sqrt(x)<<endl;
 }
}