巧用減1和位與運算

2021-06-19 08:13:42 字數 1261 閱讀 6445

有些簡單的題目,可能只需要寥寥幾行**便可被很好的解決,但是如果能用乙個更好的演算法來解決它,總能給人帶來無限的驚喜。

乙個優秀的程式設計師總是不厭其煩的一遍又一遍的優化自己的**,斤斤計較每一點空間和時間,他們總能因乙個更優的演算法而歡呼雀躍。

下面介紹兩個簡單的題目,利用減1和位與運算巧妙的來解決它們。

題目一:

請實現乙個函式,輸入乙個整數,輸出該數二進位制表示中1的個數。

題目二:

請用一條語句判斷乙個數是不是2的整數次方。

分析與解答:

對於題目一,有的人很快就能形成乙個基本的思路:先判斷整數二進位制中最右邊一位是不是1。接著把輸入的整數右移一位,此時原來處於從右邊數起的第二位移到最右邊了,再判斷是不是1。這樣每次移動一位,直到整個整數變成0為止。很快寫出如下**:

int numberof1(int n)

return count;

}

但是,此函式存在一定的缺陷,當輸入的數是負數時,如輸入的數是0x80000000,右移一位變成0xc0000000,一直做右移運算,最終會成為0xffffffff而陷入死迴圈。

為了避免死迴圈,我們可以不右移輸入的數字n。首先把n和1做與運算,判斷n的最低位是不是1。接著把1左移一位得到二,再和n做與運算......這樣反覆左移,每次都能判斷n的其中一位是不是1。基於這種思路,可把**修改如下:

int numberof1(int n)

return count;

}

這個解法中迴圈的次數等於整數二進位制的位數,32位的整數需要迴圈32次。下面給出的減1和位與運算,可使整數中有幾個1就只需要迴圈幾次。

把乙個數減去1時,如果該整數的二進位制最右邊一位是1,則最後一位變為0,其餘位不變;如果最右邊一位不是1則必定為0,乙個整數只要不是0,則至少有一位為1,減去1後,最靠右邊的1變為0,再靠右邊的0全變為1。假設n=1100(2)時,減去1的結果為1011,再和1100做位與運算,得到1000,把最右邊的1變為了0,如此反覆的做下去,即可統計出1的個數。基於以上思路,寫出的**如下:

int numberof1(int n)

return count;

}

再看問題二,相信有了上面的思路,很多人已經有了解決此問題的方案。乙個數如果是2的整數次方,則必定其二進位制表示中有且僅有一位為1,所以只要用乙個if語句判斷一下即可。

bool involution2(int n)

巧用位運算

1 用乙個表示式,判斷乙個數x是否是2的n次方 2,4,8,16.不可用迴圈語句。解析 x 2,4,8,16轉化成二進位制是10,100,1000,10000。如果減1則變成01,011,0111,01111。兩者做按位與運算,結果如果為0,則x是2的n次方。答案 x x 1 2 統計乙個整數的二進...

巧用位運算

1 不用額外空間交換兩個數字變數的值 解1 異或運算 只能交換整數 var a 3 var b 4 a a b a 7 b a b b 3 a a b a 4解2 加減法運算 非整數存在精度問題 var a 3 var b 4 a a b a 7 b a b b 3 a a b a 4解3 利用乘除...

巧用JS位運算

1.使用按位非 判斷索引存在 這是乙個很常用的技巧,如判斷乙個數是否在陣列裡面 如果url含有?號,則後面拼上 符號,否則加上?號 url url indexof 因為 1 0 1在記憶體的表示的二進位制符號全為1,按位非之後就變成了0.進一步說明 1在記憶體的表示為 0000.0001,第一位0表...