在刷題過程中,發現Python有一個和其他語言完全不一樣的地方,就是對負數的二進制表示。Python里的數是無所謂Overflow的,即沒有位數限制,因此也就無所謂補碼,因為補碼都是相對於位數來說的,32位補碼和16位補碼,肯定是不一樣的。但是這樣就導致了一個問題,就是無法直接得到32位二進制補碼。
>>> bin(1) '0b1' >>> bin(-1) '-0b1'
解決方法: 人為規定一個函數,實現轉換。而且可以設計這個函數使得可以同時對正數和負數使用得到正確的補碼。
def intToBin32(self, i): return (bin(((1 << 32) - 1) & i)[2:]).zfill(32)
用zfill補全正數的32位
如此就能獲得32位補碼,如果想得到其他位數的補碼,把32改成對應位數即可。
轉換回去:
def bin32ToInt(self, s): return int(s[1:], 2) - int(s[0]) * (1 << 31)
經過所有32位有符號數字的考驗,證明這個方法是正確的:
imin = -0x7ffffff-1
imax = 0x7fffffff
for i in range(imin, imax+1): if i != bit().bin32ToInt(bit().intToBin32(i)): print(i, "x") # 沒有輸出,說明轉換是正確的
例.更新比特Update Bits。假設有兩個32位有符號整數n和m,給出兩個位置i和j,i<j,將n中對應的位數替換為m,然后返回n的新值。例如,給出n=1024(0b10000000000),m=21(0b10101),i=2,j=6,返回1108(0b10001010100)。保證j-i+1大於等於m的寬度。
【解】這道題有位操作和字符串兩種做法,位操作需要考慮的情況還比較多,不如就利用上面的函數轉字符串做。思路非常簡單,就是先轉化為字符串,然后把n中間用m替換掉,再轉換回來。注意截取寬度比m實際寬度寬的情況。
class Solution: #@param n, m: Two integer #@param i, j: Two bit positions #return: An integer def updateBits(self, n, m, i, j): sn, sm = self.intToBin32(n)[::-1], self.intToBin32(m)[::-1][:j-i+1] newn = (sn[:i] + sm + sn[j+1:])[::-1] return self.bin32ToInt(newn) def intToBin32(self, i): return (bin(((1 << 32) - 1) & i)[2:]).zfill(32) def bin32ToInt(self, s): return int(s[1:], 2) - int(s[0]) * (1 << 31)
作者:akak18183
鏈接:https://www.jianshu.com/p/96ea0b077051
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權並注明出處。