版權申明:本文為博主窗戶(Colin Cai)原創,歡迎轉帖。如要轉貼,必須注明原文網址 http://www.cnblogs.com/Colin-Cai/p/7220506.html 作者:窗戶 QQ:6679072 E-mail:6679072@qq.com
一個函數從數學上來說可以有無數個函數列收斂於這個函數,那么程序逼近實現來說可以有無數種算法,平方根自然也不例外。
不知道有多少人還記得手算平方根,那是滿足每次在結果上添加一位,也就是按位逼近運算結果的唯一算法。至於數學上如何證明這個唯一性我就不說了,數學證明不會有那么多人有興趣。按位逼近更加適合手算,舉個大家更熟悉的例子,那就是手算除法。我這里就采用按位逼近的手算方法。
要說手算平方根,原理其實非常簡單,
一是平方根函數是嚴格單調增函數,
二就是以下這個恆等式滿足
(a*N+b)2 ≡ (a*N)2 + 2*a*b*N + b2
≡ (a*N)2 + b * ((a*N) * 2 + b)
我們實例操作一次平方根筆算,來解釋一下。
我們來求5499025的平方根。
先將5499025兩位兩位從低往高排,為
5 49 90 25
2*2<5<3*3
所以最高位為2,
然后我們再來看549的平方根,
我們假設549的平方根的整數部分是2*10+b,則根據之前的恆等式,N在這里等於10,a在這里等於2,有
549 >=(2*10)2 + b * ((2*10) * 2 + b)
整理一下,149 >= b * (40 + b)
3 * 43 < 149 < 4 * 44
所以b=3,
549的平方根整數部分是23,
再假設54990的平方根整數部分為23*10+b,
則
54990 >= (23*10)2 + b * ((23*10) * 2 + b)
整理一下,2090 >= b * (460 + b),
464 * 4 < 2090 < 465 * 5
所以b=4,
54990的平方根整數部分為234,
最后再來看5499025的平方根的整數部分,假設為234 * 10 + b,
則
5499025 >= (234*10)2 + b * ((234*10) * 2 + b)
整理一下, 23425 >= b * (4680 + b)
而5 * 4685 = 23425, 等式成立,
所以最終我們要求的平方根是2345。當然,小數位其實一樣可以用這種方法繼續算下去。
手算平方根就是如上這樣從高位一步步往地位推的過程,寫成式子的形式大致如下:
2 3 4 5
-------------------
| 5 49 90 25
2 | 4
-------------------
| 1 49
43 | 1 29 ——當前算出了2,2*10*2 = 40
-------------------
| 20 90
464 | 18 56 ——當前算出了23,23*10*2 = 460
-------------------
| 2 34 25
4685 | 2 34 25 ——當前算出了234,234*10*2 = 4680
-------------------
0
當然,如何寫不重要,知道過程便可以繼續我們的這個設計。接下去我們要去利用之前的這個算法,改裝一下,來進行二進制的開平方。
二進制的每一位不是1就是0,這樣在每次往前推一位的時候就相對簡單。
舉個例子,我們來算121的平方根,也就是二進制下1111001的平方根。
兩位兩位從低位往高位排
1 0 1 1
------------------
| 1 11 10 01
1 | 1
------------------
| 11
100 | 0 ——當前上面算出了1,1右移動兩位為100
------------------
| 11 10
1001 | 10 01 ——當前上面算出了10,1右移動兩位為1000
------------------
| 1 01 01
10101 | 1 01 01 ——當前上面算出了101,1右移動兩位為10100
------------------
0
每往右邊推1位,下面的除數就是上面當前算出來的二進制的數右移兩位再加1或者加0
之后,我們就可以用構建利用此算法的平方根了。