C++入門教程(16):二進制的運算

小古銀的官方網(wǎng)站(完整教程):http://www.xiaoguyin.com/
C++入門教程視頻:https://www.bilibili.com/video/av20868986/


加法

010 + 010為例子:加號兩邊的數(shù)值的右邊第一位都是0,相加得0;中間那一位都是1,相加得2,所以需要進位,結(jié)果變?yōu)?;左邊第一位都是0,相加得0,再加上進的位,所以結(jié)果是1。那么最后結(jié)果就是100。也就是十進制的2 + 2的結(jié)果是4。

注意:而C++中的二進制的運算都是有一個前提條件,就是必須固定位數(shù)再進行運算,如果進位時超出位數(shù)那么超出部分將會被舍棄。例如要相加的二進制數(shù)值是3位數(shù),110 + 010,按照加法運算結(jié)果應(yīng)該是1000,因為位數(shù)已經(jīng)固定三位,左邊超出的一位將被舍棄,所以結(jié)果是000。

提示:二進制表示數(shù)值時,左邊的0是可以省略的,把左邊的0寫出來是為了方便講解,如二進制的00000010可以省略寫成二進制的10,相當(dāng)于十進制的00123456也可以簡寫成123456。由于C++的二進制運算是固定位數(shù)的,所以就算你省略了左邊的0,程序也是知道左邊應(yīng)該補上多少個0。

基礎(chǔ)示例

#include <iostream>

int main(void)
{
    std::cout << "0b010 + 0b010 = " << (0b010 + 0b010) << std::endl;

    unsigned int value = 4294967295;
    std::cout << (value + 1) << std::endl;

    return 0;
}

輸出結(jié)果:

0b010 + 0b010 = 4
0

基礎(chǔ)講解

二進制的010加上二進制的010結(jié)果是二進制的100,也就是十進制2加上十進制2等于十進制的4

unsigned int是保存非負整數(shù)的int類型,它的最大值是4294967295,也就是二進制32位都是1的值,而且unsigned int是用固定的32位二進制來保存數(shù)據(jù)的,所以當(dāng)它加上1的時候,就會因為進位而超出一個位,而超出的這個位就會被舍棄,因此輸出結(jié)果就是0。

減法

101 - 011為例子:第一位相減結(jié)果是0,而第二位0減去1需要向高位借一位,因此第二位結(jié)果是1,但三位結(jié)果是0,則結(jié)果是010。也就是十進制的5 - 3結(jié)果是2

注意:由于運算需要固定位數(shù),所以上面內(nèi)容同樣也適用于減法運算,但是需要注意的是二進制只有0和1而沒有正負的概念。以010 - 011作為例子:第一位結(jié)果是1,而且向第二位借了一位;而第二位此時已經(jīng)不能正常運算了,此時雖然沒有第四位,但是它可以從第四位借一位,第四位向誰借就不管了,反正第三位可以計算了,那么第二位就可以向第三位借一位,第二位結(jié)果是1,第三位結(jié)果是1。最后結(jié)果就是二進制的111

基礎(chǔ)示例

#include <iostream>

int main(void)
{
    std::cout << "0b101 - 0b010 = " << (0b101 - 0b011) << std::endl;

    unsigned int value = 0;
    std::cout << (value - 1) << std::endl;

    return 0;
}

輸出結(jié)果:

0b101 - 0b010 = 2
4294967295

基礎(chǔ)講解

二進制的101減去二進制的011結(jié)果是二進制的010,也就是十進制的5減去3等于的2。

由于固定了32位的二進制運算,按照上面的運算方法得出的結(jié)果是二進制的32位都是1,也就是unsigned int的最大值,所以對應(yīng)的十進制結(jié)果就是4294967295。

二進制的乘法和除法

二進制的乘法和除法比較復(fù)雜,而且對C++基礎(chǔ)知識幫助不大,就不講解了。以下講解的運算是二進制特有的運算。

左移運算和右移運算

以二進制0110舉例:0110左移一位就是在右邊添加1位0,得出01100,由于固定位數(shù),所以左邊超出的1位被舍棄,結(jié)果就是1100;0110左移兩位就是在右邊添加2位0,得出011000,由于固定位數(shù),所以左邊超出的2位被舍棄,結(jié)果就是1000,以此類推。右移也是同理,0110右移1位就是0011,右移2位就是0001

在C++中左移的運算符號是<<,右移的運算符號是>>0110左移2位的代碼就是0110 << 2,0110右移2位的代碼就是0110 >> 2。

一個有意思的規(guī)律:例如0001 + 0001的結(jié)果是0010,0010 + 0010的結(jié)果是01000011 + 0011的結(jié)果是0110??梢钥闯觯阂粋€數(shù)乘以2就等于這個數(shù)左移一位,而一個數(shù)左移兩位就是這個數(shù)乘以2的2次方,以此類推。而右移也是同理。

特殊的情況,2的10次方就是1左移10位,結(jié)果就是二進制的10000000000,也就是十進制的1024。

基礎(chǔ)示例

#include <iostream>

int main(void)
{
    std::cout << (10 << 3) << std::endl;

    unsigned int value1 = 0b1000'0000'0000'0000'0000'0000'0000'0000;
    std::cout << (value1 << 1) << std::endl;

    std::cout << (10 >> 1) << std::endl;

    unsigned int value2 = 0b1;
    std::cout << (value2 >> 1) << std::endl;

    return 0;
}

輸出結(jié)果:

80
0
5
0

基礎(chǔ)講解

十進制的10左移3位,也就是十進制的10乘以2的3次方,結(jié)果就是十進制的80。

變量value1保存的數(shù)左移一位,由于unsigned int類型用32位二進制來保存數(shù)據(jù),所以當(dāng)它左移一位時,左邊的1因為超出而被舍棄,結(jié)果就是0。

十進制的10右移1位,也就是十進制的10除以2的1次方,結(jié)果就是十進制的5。

變量value2保存的數(shù)右移一位,由于unsigned int類型用32位二進制來保存數(shù)據(jù),所以當(dāng)它右移一位時,右邊的1因為超出而被舍棄,結(jié)果就是0。

與運算

在C++中,與運算的運算符號是&。

1 & 1的結(jié)果是1;1 & 0或者0 & 1的結(jié)果是0,0 & 0的結(jié)果也是0。

而二進制運算0110 & 0100的結(jié)果是0100??梢钥闯雠c運算就是二進制各個位上對應(yīng)的數(shù)進行與運算,都是1的時候結(jié)果是1,有一個0或者都是0的時候結(jié)果是0。

或運算

在C++中,或運算的運算符號是|

1 | 1的結(jié)果是1;1 | 0或者0 | 1的結(jié)果是1,0 | 0的結(jié)果也是0。

而二進制運算0110 | 0100的結(jié)果是0110。可以看出或運算就是二進制各個位上對應(yīng)的數(shù)進行或運算,都是1或者有一個是1的時候結(jié)果是1,都是0的時候結(jié)果是0。

異或運算

在C++中,異或運算的運算符號是^。

1 ^ 1的結(jié)果是0;1 ^ 0或者0 ^ 1的結(jié)果是1,0 ^ 0的結(jié)果也是0。也就是說,異或相同的數(shù)結(jié)果是0,異或不同的數(shù)結(jié)果是1,而二進制運算0110 ^ 0100的結(jié)果是0010。

取反運算

在C++中,取反運算的運算符號是~。取反運算就是二進制各個位上的數(shù),0變?yōu)?,1變?yōu)?。例如二進制運算~0110的結(jié)果是1001。

注意:取反運算時,需要注意它的數(shù)據(jù)類型,不同的數(shù)據(jù)類型的位數(shù)都不相同,而上面也說過左邊多出來的0可以省略,所以就算是同一個數(shù),如0b1101,二進制位數(shù)是4位時結(jié)果是0b0010,二進制位數(shù)是8位時結(jié)果是0b11110010,它們的值是不一樣的。所以,取反必須要注意它的數(shù)據(jù)類型喲~。

基礎(chǔ)示例

#include <iostream>

int main(void)
{
    std::cout << (0b0110 & 0b0100) << std::endl;
    std::cout << (0b0110 | 0b0100) << std::endl;
    std::cout << (0b0110 ^ 0b0100) << std::endl;

    unsigned int value = 0;
    std::cout << (~value) << std::endl;

    return 0;
}

輸出結(jié)果:

4
6
2
4294967295

基礎(chǔ)講解

二進制0100就是十進制的4,二進制的0110就是十進制的6,二進制的0010就是十進制2。二進制32位上所有位都是0,取反就是二進制32位上所有位都是1,也就是unsigned int類型的最大值4294967295。

運算符在C++代碼中的簡化

  • 按位與:a = a & b可以簡化成a &= b
  • 按位或:a = a | b可以簡化成a |= b
  • 按位異或:a = a ^ b可以簡化成a ^= b
  • 按位左移:a = a << b可以簡化成a <<= b
  • 按位右移:a = a >> b可以簡化成a >>= b

保存過大數(shù)據(jù)時注意范圍

unsinged int用二進制32位來保存數(shù)據(jù),如果用unsinged int的變量保存更大的數(shù)據(jù)會怎么樣呢?

基礎(chǔ)示例

#include <iostream>

int main(void)
{
    unsigned int value = 0b1'0000'0000'0000'0000'0000'0000'0000'0001;
    std::cout << value << std::endl;
    return 0;
}

輸出結(jié)果:

1

基礎(chǔ)講解

可以看出,用二進制32位的空間保存33位的數(shù)據(jù),它只會保存前32位數(shù)據(jù),第33位數(shù)據(jù)會被舍棄。所以,用變量保存數(shù)據(jù)時要注意不要保存過大的數(shù)值。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 第2章 基本語法 2.1 概述 基本句法和變量 語句 JavaScript程序的執(zhí)行單位為行(line),也就是一...
    悟名先生閱讀 4,565評論 0 13
  • 位運算 位運算的運算分量只能是整型或字符型數(shù)據(jù),位運算把運算對象看作是由二進位組成的位串信息,按位完成指定的運算,...
    IIronMan閱讀 8,091評論 0 2
  • 1 關(guān)鍵字 1.1 關(guān)鍵字的概述 Java的關(guān)鍵字對java的編譯器有特殊的意義,他們用來表示一種數(shù)據(jù)類型,或...
    哈哈哎呦喂閱讀 782評論 0 0
  • 運算符是處理數(shù)據(jù)的基本方法,用來從現(xiàn)有的值得到新的值。JavaScript 提供了多種運算符,本章逐一介紹這些運算...
    許先生__閱讀 710評論 0 3
  • 在我們遭遇困難和挫折時,在我們遇到過不去的坎兒的時候。朋友會勸我們,別在最難的時候放棄,你會永遠遺憾的;家人會告訴...
    周讀札記閱讀 4,251評論 66 193

友情鏈接更多精彩內(nèi)容