對應力扣題目:
參考自解答:
- dexin的解答
如何使用位運算對整數求絕對值呢?
- 對於正數,數值是其本身;
- 對於負數,需要求反碼,然後加一。
這是因爲在C++整數中,數值是以“補碼”
這種形式存儲的,對於8位的int
,如下表。
二進制表示 | 符號位 | 數值位 | 對應整數數值 |
---|---|---|---|
0000 0001 | 0 | 000 0001 | 1 |
0000 0010 | 0 | 000 0010 | 2 |
1111 1111 | 1 | 111 1111 | -1 |
1111 1110 | 1 | 111 1110 | -2 |
對於1111 1111
,將其取反0000 0000
,再加1,得0000 0001
,即將-1
轉換成了+1
。
求 int 的絕對值操作如下
int abs(int k) {
return k ^ (k >> 31) - (k >> 31);
}
解釋如下:
- 首先,
k>>31
代表將有符號的數組右移31位: -
- 因爲
int
一共有32位,其中最高位是符號位,代表正負;
- 因爲
-
- 對於正數,
k >> 31
後即爲0000 0000 0000 0000 0000 0000 0000 0000
,而對於負數,k >> 31
後即爲1111 1111 1111 1111 1111 1111 1111 1111
;
- 對於正數,
- 接着,
a = a ^ b
表示異或: -
- 當
b
爲全0時,該操作相當於沒做;
- 當
-
- 當
b
爲全1時,該操作相當於取反碼;
- 當
- 最後,
a - b
運算實則不是位運算,屬於整數運算: -
- 當
b
爲全0時,該操作相當於沒做;
- 當
-
- 當
b
爲全1時,該操作相當於加1(-(-1)
)。
- 當
因此,上述操作也即是:
- 對正數什麼都沒做;
- 對負數取了負值。
這就是位運算的絕對值操作。
對於long
類型,將31改成63即可。
這屬於模板方法,應熟練。