1. 程式人生 > 其它 >位運算總結(持續更新)

位運算總結(持續更新)

字母大小寫‘’高效‘’轉換

日常對leetcode的easy題重拳出擊時發現有道題目709. 轉換成小寫字母的題解有點意思。這道題目雖然簡單,只是將給定的字串中的大寫字母轉小寫返回。但看到題解有人分析了下如何利用位運算進行轉換,這裡簡單分析記錄一下。通過查詢ASCII表可知:

  • 大寫字母\(A - Z\)的 ASCII 碼範圍為$ [65, 90]$

  • 小寫字母 \(a - z\) 的 ASCII 碼範圍為 \([97, 122]\)

因此常見思路便是先判定字母在$ A - Z \(範圍內後直接ch=ch-'A'+'a'即可,但仔細分析下可以發現\)[65,96]$ 對應的二進位制表示為 \([(01000001)_2, (01011010)_2]\)

而32 對應的二進位制表示為$ (00100000)_2$ ,而對於 \([(01000001)_2, (01011010)_2]\)內的所有數,表示 32 的那個二進位制位是 0,因此可以將ch 的 ASCII 碼與 32進行按位或運算來替代與32 的加法運算。

進一步推廣可得:(ch為字母)

  • 大寫\(\rightarrow\)小寫、小寫\(\rightarrow\)大寫 : ch ^= 32
  • 大寫\(\rightarrow\)小寫、小寫\(\rightarrow\)小寫 : ch |= 32
  • 小寫\(\rightarrow\)大寫、大寫\(\rightarrow\)大寫 : ch &=-33

可以看出 ASCII 的表設計的非常巧妙,於是我順便看了下c庫函式中的tolower( )

函式是否也用了位運算,但貌似設計者並未考慮這些。╮(╯▽╰)╭

    //ctype.h
        __forceinline int __CRTDECL __ascii_tolower(int const _C)
    {
        if (_C >= 'A' && _C <= 'Z')
        {
            return _C - ('A' - 'a');
        }
        return _C;
    }

判斷奇偶

正常的做法應當是判斷x%2!=0,但有的時候可能會錯誤的通過x%2==1判斷。具體原因可見負數取模、取模與取餘

。這個時候更推薦的做法是用x&1

if (n & 1) {
	//奇數
    } else {
       	 //偶數
    }

很容易理解一個整數為奇數時其二進位制最後一位一定是1,而此時我們只需要將n與\((00...001)_2\)進行一下與運算只考慮最後一位即可簡潔高效的進行判斷。