日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++描述的位运算总结

發布時間:2025/3/20 c/c++ 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++描述的位运算总结 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2021.05.07更新:添加異或運算的性質
2020.03.23更新:添加位運算符~的應用
2020.02.24更新:添加目錄、調整格式。
2020.01.04更新:反碼的缺點和使用,以及補碼的優點。


文章目錄

  • 一、前言
  • 二、數的二進制表示
    • 1. 原碼
    • 2. 反碼
    • 3. 補碼
  • 三、運算符
    • 1. 按位與 &
    • 2. 按位或 |
    • 3. 按位取反 ~
    • 4. 按位異或 ^
    • 4. 左移 <<
    • 5. 右移 >>

一、前言

之前大一上課的時候,老師說位運算不考,當時就沒有認真去學習。后來學算法的時候,發現大佬的代碼中總會摻雜著一些位運算操作,為了理解那些代碼,前前后后也看了幾次位運算操作,但是沒有很好地記錄下來。現在又遇到了,借此機會寫個總結。

由于位運算都是直接對整數在內存中的二進制數進行操作的,所以位運算的效率會相對比較高。

二、數的二進制表示

二進制數最高位為符號位,0表示正,1表示負(一般我們都不寫出來)。所以C語言中的int(32位整數)的范圍是?231-2^{31}?231231?12^{31}-1231?1,第32位用來做符號位了。
正數的二進制表示即為它的原碼,負數的二進制表示為它的補碼。

1. 原碼

把一個整數的絕對值轉換為二進制數,再加上符號位就是該整數的原碼。例如:
+9的原碼為0 0001001(即為+9的二進制表示)
-9的原碼為1 0001001

2. 反碼

正數的反碼與它的原碼相同,負數的反碼符號位不變,數值部分為原碼的按位取反。例如:
+9的反碼為0 0001001
-9的反碼為1 1110110

由于反碼0的表示不唯一、表示數的范圍比補碼少一個最小負數、運算時必須考慮循環進位,因此反碼在計算機中很少被使用,有時用作數碼變換的中間表示形式。

3. 補碼

正數的補碼與它的原碼相同,負數的補碼為它的反碼+1。例如:
+9的補碼為0 0001001
-9的補碼為1 1110111(即為-9的二進制表示)

因為補碼0的表示是唯一的,于是減少了+0和-0之間的轉換;少占用了一個編碼表示,使得補碼能比原碼多表示一個最小負數。

三、運算符

1. 按位與 &

對兩個等長的(不夠在前面用0補)二進制數進行按位與運算,如果對應位都為1,則該位為1,否則該位為0。
例如:求9&3,將它們轉換為二進制數(以下都是先這樣操作)

1001 0011 ----- 0001

應用:

  • 通常我們可以用n&1來判斷n是奇數還是偶數,因為奇數的二進制最后一位都是1。

    #include <iostream> using namespace std; int main() {for (int i = 0; i < 10; i++)if (i & 1) cout << i << " ";return 0; }

    輸出結果
    1 3 5 7 9

  • 用 n&(-n) 求非負數在二進制表示下最低位1以及它后面的0構成的數值。(這一求解應用在樹狀數組中)

  • 對于任意整數 xxx,令 x=x&(x?1)x=x \&(x-1)x=x&(x?1),該運算將 xxx 的二進制表示的最后一個 111 變成 000。于是,我們可以利用該性質快速求一個數二進制位有多少個1。

    #include <iostream> using namespace std; int main() {int x, i;cin >> x;for (i = 0; x != 0; i++)x &= (x - 1);cout << i << endl;return 0; }
  • 2. 按位或 |

    對兩個等長的(不夠在前面用0補)二進制數進行按位或運算,如果對應位都為0,則該位為0,否則該位為1。
    例如:求9|3

    1001 0011 ----- 1011

    3. 按位取反 ~

    ~a表示對a的二進制表示的每一位進行取反,即0變為1,1變為0。例如:求~9

    1001 ----- 0110

    應用:
    用于求相反數,公式為:~n + 1

    #include <stdio.h> int main () {int n = 10;printf("%d ", ~n + 1);return 0; }

    輸出結果
    -10

    4. 按位異或 ^

    對等長二進制模式按位或二進制數的每一位執行邏輯按位異或操作,操作的結果是如果某位不同則該位為1, 否則該位為0。
    (摘自百度百科)

    例如:求9^3(很多新手會誤以為是939^393

    1001 0011 ----- 1010

    ⊕\oplus 為異或運算,異或運算滿足以下性質:

  • x⊕x=0x \oplus x = 0xx=0
  • x⊕y=y⊕xx \oplus y = y \oplus xxy=yx(交換律);
  • (x⊕y)⊕z=x⊕(y⊕z)(x \oplus y) \oplus z = x \oplus (y \oplus z)(xy)z=x(yz)(結合律);
  • x⊕y⊕y=xx \oplus y \oplus y = xxyy=x(自反性);
  • ?i∈Z?i∈Z,有4i⊕(4i+1)⊕(4i+2)⊕(4i+3)=0\forall i \in Z?i∈Z,有 4i \oplus (4i+1) \oplus (4i+2) \oplus (4i+3) = 0?iZ?iZ4i(4i+1)(4i+2)(4i+3)=0
  • 應用:

  • 利用按位異或的自反性,我們可以不需要用輔助變量也能實現兩個數的交換(裝逼用【被打】)#include <iostream> using namespace std; int main() {int a = 10, b = 5;a = a ^ b;b = a ^ b;a = a ^ b;cout << a << " " << b << endl;return 0; }

    輸出結果
    5 10

  • 4. 左移 <<

    a<<n 表示將 a 的二進制表示數向左移動 n 位,即在后面添加 n 個 0。同樣,也就相當于 a 乘以 2n2^n2n

    #include <iostream> using namespace std; int main() {for (int i = 0; i < 10; i++)cout << (1<<i) << " ";return 0; }

    輸入結果
    1 2 4 8 16 32 64 128 256 512

    5. 右移 >>

    a>>n 與上面的左移剛好相反,表示將a的二進制表示數往右移動n位,即直接去掉a后面的n位,相當于a除以 2n2^n2n。通常我們可以利用 n>>=1 來代替 n /= 2來提高運算效率。

    總結

    以上是生活随笔為你收集整理的C++描述的位运算总结的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。