1. 程式人生 > >劍指offer 12. 二進位制中1的個數

劍指offer 12. 二進位制中1的個數

原題

輸入一個整數,輸出該數二進位制表示中1的個數。其中負數用補碼錶示。

My solution (Wrong)

# -*- coding:utf-8 -*-
class Solution:
    def NumberOf1(self, n):
        # write code here
        abs_n = abs(n)
        count = 0
        while abs_n != 0:
            abs_n = (abs_n - 1) & abs_n
            count += 1
        return count

答案證明這種方案是錯誤的,因為 -1 的補碼是32,而不是1; 而若是直接使用:

def NumberOf1(self, n):
    count = 0
    while n != 0:
        count += 1
        n = n & (n-1)
    return count

但是!上述程式碼在n小於0時會無限迴圈!(Python3.6.1中) 列印n 和 n的二進位制表示的值,發現了一個很奇怪的現象。以n=-10舉例: 初始時n的二進位制值為:

‘0b11111111111111111111111111110110’

迴圈計數29次後,n的10進位制值為:-2147483648,n的二進位制值為:

‘0b10000000000000000000000000000000’

迴圈計數30次後,n的10進位制值為:-4294967296,n的二進位制值為:

‘0b0’

也就是說,此時雖然n的二進位制值為0b0,但是記憶體中顯示n的十進位制值為-4294967296,滿足 n!=0 的條件, 迴圈會繼續執行。在此之後的迴圈中,n的二進位制表示一直顯示為0b0, 但記憶體中n的十進位制數繼續不斷減少。。。

為什麼呢? 我在獲取上述n的二進位制值時,用的語句是:

print(bin(n & 0xffffffff ))

而直接呼叫bin語句,會發現:

bin(-10)
'-0b1010'
bin(-12)
'-0b1100'
bin(-16)
'-0b10000'
... ...
bin
(-2147483648) '-0b10000000000000000000000000000000' bin(-4294967296) '-0b100000000000000000000000000000000' bin(-8589934592) '-0b1000000000000000000000000000000000' bin(-17179869184) '-0b10000000000000000000000000000000000'

即在當前情況下,繼續迴圈時n的二進位制不斷補0,使得n繼續不斷減小。。。也就是說Python3.6.1中int型別不止32位。。。

問了度娘之後才知道,原來Python2的int型別有32位和64位一說,但到了Python3,當長度超過32位或64位之後,Python3會自動將其轉為長整型,長整型理論上沒有長度限制。

正確方案

# -*- coding:utf-8 -*-
class Solution:
    def NumberOf1(self, n):
        # write code here
        abs_n = n
        count = 0
        while abs_n & 0xffffffff != 0:
            abs_n = (abs_n - 1) & abs_n
            count += 1
        return count