閱讀 csapp v3 時,練習題 2.13 頗有意思。練習題描述以下。app
位設置是對於參數 mask 中每個爲 1 的位,那麼參數 x 中相應位則被設置爲 1 ;位清除是對於參數 mask 中每個爲 1 的位,那麼參數 x 中相應位則被設置爲 0 。假設有兩個函數 bis 和 bic 來實現位設置和位清除,請使用這兩個函數實現兩個數的異或結果。函數
小提示:可使用的位運算是與、或和非。測試
local function bis(x, mask) return x | mask end local function bic(x, mask) return x & ~mask end
什麼是異或呢?異或就是兩個值中,至少有一個爲真,但不全爲真,那麼結果就是真,不然結果就是假。對於兩個二進制位,至少有一個位爲 1 但不全爲 1,那麼結果就是 1,不然結果是 0 。
也就是說只有 (1 異或 0) 或者 (0 異或 1) 結果才爲 1,其他結果都爲 0 。只要兩個位不相同,那麼結果就是 1 。因此問題變成了如何判斷兩個位不一樣。
與運算要求兩個位都是 1 時,結果纔是 1,所以 1 & ~0
結果是 1 而 ~0 & 1
結果也是 1,這作實現了兩個位不一樣,而結果是 1 。因爲存在 1 & ~0
或 ~0 & 1
,所以異或運算可被拆分爲 (1 & ~0) | (~0 & 1)
。推廣成 (x & ~y) | (~x & y)
。lua
通過分析後,發現徹底能夠代入上面的函數。因而實現異或的代碼以下。操作系統
local function exor(x, y) return bis(bic(x, y), bic(y, x)) end
完整的測試用例 Lua 代碼以下。code
local function bis(x, mask) return x | mask end local function bic(x, mask) return x & ~mask end local function exor(x, y) return bis(bic(x, y), bic(y, x)) end local x, y = 0x12345678, 0x87654321 assert(exor(x, y) == x ~ y
參考內容io