使用PHP,給定一個數,判斷這個數是不是二的N次方
這樣看似簡單的一個面試題, 實際牽出了不少基礎知識,本章在爲你們補習基礎知識的狀況下來解答這道題。先亮出答案php
function exponentiation($number) { if ($number < 0) { return false; } if (($number & ($number - 1)) == 0) { return true; } else { return false; } } exponentiation (2); exponentiation (8); exponentiation (16); exponentiation (32); exponentiation (128);
這是查閱後的最最標準的答案,其餘相似經過循環等等答案就略過把。程序員
實際這道面試題考的並不是是算法,而是做爲開發人員的你「底子」夠不夠。
運算符應該是每門語言hello world 後立馬要學習的。運算符分不少種,賦值運算符,比較運算符等等。我想大多自學或者培訓出道的沒有通過系統化學習的童鞋的,對這塊的知識應該很薄弱把。固然賦值、比較什麼的很熟悉,因業務基本逃不過這些。但對位運算符,你真的吃透了嗎?面試
這道題的考點一是位運算符的使用,上面說過了本題考察的並不是算法,而是你對二進制的瞭解,而在php中能操做二進制的運算符 貌似 (個人知識範圍內) 只有位運算符
本道面試題用到了 & 因此不詳解其餘的運算符,須要更多瞭解請移步官方
http://php.net/manual/zh/lang...算法
運算符 | 附加信息 |
---|---|
& | 按位與運算符 |
^ | 按位異或運算符 |
按位與以簡單易懂的方式來說就是二進制位不相同的抵消,相同的保留學習
舉幾個栗子spa
公式 -> 轉爲二進制後的公式 -> 二進制結果 -> 十進制結果
2 & 3 -> 0010 & 0011 -> 0010 = 2 10 & 7 -> 1010 & 0111 -> 0010 = 2 32 & 70 -> 0100000 & 1000110 -> 0000000 = 0
按位異或以簡單易懂的方式來說就是二進制位相同的抵消,不相同的保留.net
舉幾個栗子3d
公式 -> 轉爲二進制後的公式 -> 二進制結果 -> 十進制結果
2 ^ 3 -> 0010 ^ 0011 -> 0001 = 1 10 ^ 7 -> 1010 ^ 0111 -> 1101 = 13 32 ^ 70 -> 0100000 ^ 1000110 -> 1100110 = 102
借用百度百科上的一段話code
二進制是計算技術中普遍採用的一種數制。二進制數據是用0和1兩個數碼來表示的數。它的基數爲2,進位規則是「逢二進一」,借位規則是「借一當二」。
二進制自己就是爲2這個數字而使用的,因此說這道面試題直指二進制的使用是沒錯的。2的n次方則就是blog
n | 公式 | 結果 |
---|---|---|
1 | 2 | 2 |
2 | 2x2 | 4 |
3 | 2x2x2 | 8 |
4 | 2x2x2x2 | 16 |
換算成二進制的表格是
n | 公式 | 結果 |
---|---|---|
1 | 2 | 000010 |
2 | 2x2 | 000100 |
3 | 2x2x2 | 001000 |
4 | 2x2x2x2 | 010000 |
由此看出2的n次方的二進制最高位是1,其他補0,(n&(n-1))==0 而且 n> 0 的狀況下一定是2的n次方,爲何要-1呢?在二進制中每一位必須都不相同&後纔會得出0,上述已經講解了&的運算結果。例如十進制的16
16 & (16 - 1) = 010000 & (001111) = 0
不要糾結(n&(n-1))==0 這個公式是怎麼來的,做爲程序員,我感受應該把更多時間放到反推上面來,去應證這個公式的正確性。
驗證是不是2的n次方,笨的方法就是一直除2,除到最後等於0則就是2的次方,因此公式如上
若是是2個二進制進行運算時,計算機會統一位數,例如
01 011 <------> 001 011
計算機會將01自動補一位爲001去方便運算。
在二進制中,第一位爲1的是負數,0是正數。若是沒有補零的狀況下
10000000000 01111111111
雖然計算後也是0,但它並非2的n次方,由於第一組二進制是負數。
由上述題補充的另一道題
給定任意數,計算是2的幾回方?
function power($number){ if ($number < 0) { return false; } if (($number & ($number - 1)) == 0) { // 數學很差的,就看下面的方法 // $number = decbin($number); // return (mb_strlen($number)-1); // 數學能夠的就看下面的方法 return floor(log($number,2)); } else { return false; } }
感謝你看到這裏,我也是文中提起的沒好好學基礎的一名程序員,但當你看到我這篇文章後,但願你也能夠提起精神,去重溫下基礎,對你將來的職業生涯會起做用的。本章內容純屬本身理解,若有出入,請大佬們監督批評,謝謝🙏