劍指offer上的一道原題,鑽了個牛角尖
求二進位制中1的個數
問題出現在負數,因為要保持負數的性質,所以對負數進行右移操作後將在首位重新補1,若干次右移後將變為0xffffffff.
如果要去掉負數的符號位,可以考慮用:
int a=-127;
a=a^(0x80000000);
0x80000000就是32位中首位為1,而異或對於a的後31位來說,與0異或的結果仍未0,而對於首位,1與0異或將為0.
在這個基礎上右移得到的1的個數就是除首位1之外的1的個數。
最後對負數把首位的1個數補上即可。
實際上處理的時候完全可以通過對1左移的形式來獲得a中1的個數,完全不必要如此麻煩。
另外劍指offer中還有乙個解法:
(n-1)&n;
假設對於n,其右側第乙個不為0的位置為m,則n-1使m為0,m右側全為1。在將n-1與n進行&操作則將m及m右側全部置位0。
因此while(n)
(n-1)&n;
將使n逐次消掉其右側的1
負數的位運算問題
原碼 反碼和補碼 乙個數可以分成符號位 0正1負 真值,原碼是我們正常想法寫出來的二進位制。由於計算機只能做加法,負數用單純的二進位制原碼書寫會出錯,於是大家發明了反碼 正數不變,負數符號位不變,真值部分取反 再後來由於 0,0的爭端,於是改進反碼,變成補碼 正數不變,負數符號位不變,真值部分取反,...
關於負數求模運算
當我們遇到 2 3的時候,怎麼運算呢?通常乙個數m mod n 可以將m表示為 k n r 其中0 r n 1就是餘數,也是求模的結果。當m為負數的時候,這時候有兩種方法 1 先將負號提出去,直接求 m n,之後加上負號,最後還要加上n,就是最終結果了 例如 5 3 5 3 2 2 3 1 即 5 ...
關於位運算
今天看k神的一篇題解,看到一些關於位運算的技巧。又想起以前學長川哥給的一篇位運算對集合處理的技巧的pdf。所以就一起整理一下。各種位運算子的功能就不累述了。集合的位運算表示 來自川哥給的pdf 基本表示 1.空集 0 2.全集 1 3.只含有第 i 個元素的集合1 集合間的操作 1.s 與 t 的並...