二進(jìn)制基礎(chǔ)運(yùn)算整理

  • 原碼备畦、反碼和補(bǔ)碼

    在正常的運(yùn)算規(guī)則下低飒,我們熟悉的十進(jìn)制會(huì)轉(zhuǎn)化成二進(jìn)制在計(jì)算機(jī)中表示,這時(shí)的二進(jìn)制就是原碼表示懂盐,在計(jì)算機(jī)中褥赊,為了簡(jiǎn)化運(yùn)算單元的邏輯處理、降低硬件電路復(fù)雜度和成本莉恼,只有加法器的硬件電路拌喉,計(jì)算機(jī)的減法是通過(guò)數(shù)學(xué)變換把其轉(zhuǎn)化成加法運(yùn)算,比如5-2俐银,也就是5+(-2)尿背,但是如果用原碼形式去運(yùn)算5+(-2)得到的值卻不是我們想要的值,所以經(jīng)過(guò)探索捶惜,又出現(xiàn)了反碼和補(bǔ)碼田藐,至于他們有什么作用,繼續(xù)往下看吱七。

    • 原碼

      原碼就是真值的二進(jìn)制表示汽久,最高位表示符號(hào)位,整數(shù)的符號(hào)位是0陪捷,負(fù)數(shù)的符號(hào)位是1回窘。

      比如十進(jìn)制真值是6,那么八位二進(jìn)制的原碼就是00000110市袖,最高位是0表示正數(shù)啡直;十進(jìn)制的-3的八位二進(jìn)制表示為10000011,最高位1表示負(fù)數(shù)苍碟。6-3 = 6+(-3) = 00000110+10000011 = 10001001 = -9酒觅,很顯然它不是正確值3。

    • 反碼

      反碼的規(guī)則是正數(shù)的反碼是它本身微峰,負(fù)數(shù)的反碼是符號(hào)位不變舷丹,其余位取反。

      還是上面的例子蜓肆,6+(-3)的反碼表示為00000110 + 11111100 = 100000010颜凯,最高位符號(hào)位溢出舍掉,即00000010 = 2 仗扬,因?yàn)樯釛壓蟮淖罡呶皇?症概,所以不需要再取反恢復(fù)成原碼,但這也不是正確結(jié)果3早芭,但是他們之間好像有點(diǎn)聯(lián)系彼城,-3原碼10000011和其反碼11111100,一個(gè)是-3,一個(gè)是-124募壕,很多資料都是在補(bǔ)碼的時(shí)候引入<font color="red">“同余”</font>的概念调炬,但我覺(jué)得在反碼的時(shí)候引入更合理,因?yàn)樵谖铱催^(guò)一些資料之后舱馅,我還是不明白為什么是從反碼過(guò)渡到補(bǔ)碼而不是直接從原碼到補(bǔ)碼缰泡。

      • 同余和模的概念

        那同余的概念就是兩個(gè)數(shù)對(duì)同一個(gè)固定的值取余的結(jié)果是一樣的,則說(shuō)明這兩個(gè)值是同余的關(guān)系代嗤,這里的固定值通常是指一個(gè)系統(tǒng)中的最大值匀谣,類比生活中的鐘表,在鐘表系統(tǒng)中资溃,最大值就是12,過(guò)了十二就又會(huì)從1開始烈炭,如果此時(shí)的時(shí)間是3點(diǎn)整溶锭,那么要修改成6點(diǎn)有兩種方式,一種是順時(shí)針撥到6點(diǎn)符隙,此時(shí)指針走了3圈趴捅,另一種是逆時(shí)針撥到6點(diǎn),此時(shí)指針走了9圈霹疫,那么3和9就是對(duì)于12的一對(duì)同余數(shù)拱绑,12就是這個(gè)系統(tǒng)的模。

      • 思想帶入二進(jìn)制

        回到八位二進(jìn)制丽蝎,因?yàn)榘宋欢M(jìn)制的最高位是符號(hào)位猎拨,所以它的真值表示范圍就是-127~127(即11111111~01111111),負(fù)數(shù)范圍相當(dāng)于逆時(shí)針屠阻,正數(shù)范圍相當(dāng)于順時(shí)針红省,所以它的模應(yīng)該是127,但并不是国觉,因?yàn)橄鄬?duì)于鐘表吧恃,它多了一個(gè)0,鐘表的12就等于0麻诀,0就等于12痕寓,所以它的模就是12,而這里的八位二進(jìn)制的0和127不表示同一個(gè)值蝇闭,所以它的模應(yīng)該是127+1 = 128呻率。

      • 按位取反就是得到同余數(shù)

        前面的-3和-124就是原碼反碼的關(guān)系,按照鐘表環(huán)形系統(tǒng)的模定義來(lái)說(shuō)丁眼,把0和-127兩端連接起來(lái)筷凤,這個(gè)點(diǎn)假設(shè)叫x,那-3到x的距離在兩個(gè)方向上的前進(jìn)步徑分別是-3和124(這里假設(shè)-3、-2藐守、-1挪丢、0的方向是負(fù)方向,-3卢厂、-4乾蓬、-5...-127的方向是正方向),所以按位取反就是取得同余數(shù)的絕對(duì)值慎恒。

      經(jīng)過(guò)上面的分析任内,那么上面的-3的反碼-124少加個(gè)一個(gè)值(0),所以應(yīng)該是-125融柬,也就是11111101死嗦,那最后的結(jié)果就是00000011 = 3,這正是我們的正確結(jié)果粒氧。

    • 補(bǔ)碼

      正數(shù)的補(bǔ)碼是它本身越除,負(fù)數(shù)的補(bǔ)碼等于其反碼+1,之所以加1就是因?yàn)槎M(jìn)制和鐘表不一樣的它是線性結(jié)構(gòu)外盯,-127和0不是同一個(gè)值摘盆,所以我覺(jué)得補(bǔ)碼的補(bǔ)在于補(bǔ)差的那個(gè)0,同余的概念應(yīng)該存在于反碼的按位取反中饱苟,負(fù)數(shù)x的補(bǔ)碼的絕對(duì)值也就是2的n次冪+x(注意x是負(fù)數(shù))孩擂。

  • 邏輯位運(yùn)算符&、|箱熬、~类垦、^、<<坦弟、>>

    在很多源碼的閱讀中护锤,較深入的部分、接近底層的部分都會(huì)看到一些二進(jìn)制中的邏輯運(yùn)算符酿傍,有的時(shí)候簡(jiǎn)單的邏輯運(yùn)算符就能表達(dá)一種動(dòng)作烙懦、一個(gè)含義,出于求知欲赤炒,這里整理一下基本的邏輯運(yùn)算符的意義和在開發(fā)中他們通常來(lái)做些什么氯析。

    • 與運(yùn)算‘&’

      兩個(gè)二進(jìn)制位相與,二者都為1的時(shí)候才得1莺褒,比如1101&0111 = 0101掩缓。

    • 或運(yùn)算‘|’

      兩個(gè)二進(jìn)制位相或,有一個(gè)為1即得1遵岩,比如1101 | 0001 = 1101你辣。

    • 異或運(yùn)算‘^’

      兩個(gè)二進(jìn)制位異或運(yùn)算巡通,二者不同才得1,比如1101 ^ 0111 = 1010舍哄。

    • 非運(yùn)算‘~’

      單目運(yùn)算符宴凉,一個(gè)二進(jìn)制位非運(yùn)算,本以為是按位取反表悬,其實(shí)并沒(méi)有這么簡(jiǎn)單弥锄,c語(yǔ)言中unsigned修飾的整型非運(yùn)算就相當(dāng)于按位取反,但是對(duì)于非unsigned修飾的整數(shù)來(lái)講蟆沫,比如java中的整型都是有符號(hào)的籽暇,這些有符號(hào)的整數(shù)進(jìn)行非運(yùn)算的結(jié)果卻別有洞天,比如在java中~5得到的卻是-6饭庞,而按照按位取反的邏輯它應(yīng)該是010=2戒悠。

      原因在于無(wú)符號(hào)的數(shù)都是正數(shù),相當(dāng)于你取反的值就是你的真值舟山,但是有符號(hào)數(shù)的運(yùn)算是帶著符號(hào)位一起做的救崔,比如說(shuō)有符號(hào)數(shù)5,二進(jìn)制應(yīng)該是0101捏顺,最高位0代表正數(shù),~運(yùn)算會(huì)轉(zhuǎn)成1010纬黎,因?yàn)槭钦龜?shù)幅骄,所以補(bǔ)碼也是這個(gè),計(jì)算機(jī)的有符號(hào)數(shù)都是通過(guò)補(bǔ)碼運(yùn)算的本今,無(wú)論是不是負(fù)數(shù)拆座,所以這里會(huì)把1010當(dāng)成負(fù)數(shù)補(bǔ)碼對(duì)待,那它的真值就是1110=-6冠息,這就是~5 = -6的由來(lái)挪凑。

    • 左移‘<<’

      二進(jìn)制所有位整體左移若干位,若高位溢出則舍棄逛艰,低位補(bǔ)0躏碳。

      比如5 << 1= 101 << 1 = 1010 = 10,可以發(fā)現(xiàn)這里的10是5的2倍散怖,101 << 2 = 10100 = 20菇绵,所以左移n位就是擴(kuò)大至原來(lái)的2的n次冪倍。

    • 右移‘>>’

      和左移相反镇眷,整體右移n位咬最,數(shù)值減小2的n次冪,如果是正數(shù)欠动,左邊補(bǔ)0永乌,如果是負(fù)數(shù)左邊補(bǔ)1,因?yàn)槭钦停詴?huì)舍棄小數(shù)點(diǎn)后面的翅雏,譬如5>>1 = 101>>1=10 = 2圈驼。

    • 無(wú)符號(hào)右移‘>>>’

      相比于>>,不同的是左邊都是補(bǔ)0枚荣。

    • 實(shí)際開發(fā)場(chǎng)景應(yīng)用

      現(xiàn)在考慮一個(gè)場(chǎng)景碗脊,Java中有4個(gè)int型變量NONE = 0 = 00、A = 1 = 01橄妆、B = 2 = 10衙伶、ANY = 3 = 11,他們分別代表不同的模式害碾,可能需要通過(guò)switch根據(jù)這個(gè)模式去做不同的事情矢劲,ANY = A | B,NONE = A & B慌随,那么假設(shè)現(xiàn)在傳進(jìn)來(lái)一個(gè)mode是x芬沉,我們要求x是A或者ANY,那么可以通過(guò)x & A 阁猜!= 0 來(lái)確定丸逸。這種方式就是通過(guò)按照不同的二進(jìn)制位來(lái)代表不同的東西,通過(guò)邏輯運(yùn)算判斷屬不屬于剃袍。

      實(shí)際RxJava中requestFusion用到了這種方式:

      @Override
      public int requestFusion(int mode) {
          if ((mode & ASYNC) != 0) {
              outputFused = true;
              return ASYNC;
          }
          return NONE;
      }
      
    • LeetCode中的一個(gè)題

      給定一個(gè)包含n+1個(gè)整數(shù)的數(shù)組黄刚,其數(shù)字在1到n之間,內(nèi)部存在唯一的一個(gè)重復(fù)數(shù)民效,請(qǐng)找出它憔维。

      做法有很多種,我們這里使用位運(yùn)算符來(lái)做:

      int test(int[] nums){
        int base = 0;
        for(i : nums){
          if(base == (base | (1 << i)))
            return i;
          base |= (1 << i);
        }
      }
      

      首先從第一個(gè)元素開始畏邢,比如是3业扒,則1<<3 = 1000,base|1000 = 1000舒萎,不相等程储,所以base = 1000,此時(shí)第4位已經(jīng)是1了臂寝,表示這個(gè)位置有過(guò)記錄了虱肄,假如再次讀到3的時(shí)候,還是只是會(huì)在第4位變成1交煞,也就是說(shuō)讀到重復(fù)數(shù)的時(shí)候咏窿,同樣位置的二進(jìn)制位已經(jīng)變成過(guò)1了,base | (1 << i)和之前的base才會(huì)相同素征。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末集嵌,一起剝皮案震驚了整個(gè)濱河市萝挤,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌根欧,老刑警劉巖怜珍,帶你破解...
    沈念sama閱讀 219,270評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異凤粗,居然都是意外死亡酥泛,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門嫌拣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)柔袁,“玉大人,你說(shuō)我怎么就攤上這事异逐〈匪鳎” “怎么了?”我有些...
    開封第一講書人閱讀 165,630評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵灰瞻,是天一觀的道長(zhǎng)腥例。 經(jīng)常有香客問(wèn)我,道長(zhǎng)酝润,這世上最難降的妖魔是什么燎竖? 我笑而不...
    開封第一講書人閱讀 58,906評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮要销,結(jié)果婚禮上底瓣,老公的妹妹穿的比我還像新娘。我一直安慰自己蕉陋,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評(píng)論 6 392
  • 文/花漫 我一把揭開白布拨扶。 她就那樣靜靜地躺著凳鬓,像睡著了一般。 火紅的嫁衣襯著肌膚如雪患民。 梳的紋絲不亂的頭發(fā)上缩举,一...
    開封第一講書人閱讀 51,718評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音匹颤,去河邊找鬼仅孩。 笑死秀又,一個(gè)胖子當(dāng)著我的面吹牛桐绒,可吹牛的內(nèi)容都是我干的仙粱。 我是一名探鬼主播岔乔,決...
    沈念sama閱讀 40,442評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼洼专,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼军掂!你這毒婦竟也來(lái)了嫡意?” 一聲冷哼從身側(cè)響起秆撮,我...
    開封第一講書人閱讀 39,345評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎船侧,沒(méi)想到半個(gè)月后欠气,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,802評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡镜撩,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評(píng)論 3 337
  • 正文 我和宋清朗相戀三年预柒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片袁梗。...
    茶點(diǎn)故事閱讀 40,117評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡宜鸯,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出围段,到底是詐尸還是另有隱情顾翼,我是刑警寧澤,帶...
    沈念sama閱讀 35,810評(píng)論 5 346
  • 正文 年R本政府宣布奈泪,位于F島的核電站适贸,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏涝桅。R本人自食惡果不足惜拜姿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望冯遂。 院中可真熱鬧蕊肥,春花似錦、人聲如沸蛤肌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)裸准。三九已至展东,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間炒俱,已是汗流浹背盐肃。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留权悟,地道東北人砸王。 一個(gè)月前我還...
    沈念sama閱讀 48,377評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像峦阁,于是被迫代替她去往敵國(guó)和親谦铃。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容