引言
? ? ????簡單來說計(jì)算機(jī)就是由晶體管和電路板組成的電子設(shè)備镀赌,它只能處理由0和1組成的二進(jìn)制元數(shù)據(jù)氯哮。在這種物理表現(xiàn)形式下,設(shè)定2為基數(shù)商佛,數(shù)位使用2^n形式進(jìn)行計(jì)數(shù)喉钢,進(jìn)位規(guī)則是“逢二進(jìn)一”,借位規(guī)則是“借一當(dāng)二”良姆,所以稱為二進(jìn)制肠虽。
什么是有符號(hào)數(shù)、無符號(hào)數(shù)玛追?
? ? ? ? 二進(jìn)制分為有符號(hào)和無符號(hào)二進(jìn)制數(shù):無符號(hào)二進(jìn)制數(shù)均表示正數(shù)税课;有符號(hào)二進(jìn)制數(shù)的最高位是符號(hào)位闲延,其余位是數(shù)字位,符號(hào)位為1時(shí)韩玩,表示負(fù)數(shù)垒玲,為0時(shí)表示正數(shù)。
采用余數(shù)思想處理數(shù)據(jù)“溢出”
????????Java中都是有符號(hào)二進(jìn)制數(shù)找颓。例如:int類型的數(shù)字合愈,表示占4個(gè)字節(jié)(每個(gè)字節(jié)8個(gè)bit)的32bit的二進(jìn)制數(shù)。根據(jù)數(shù)學(xué)中的排列組合击狮,一個(gè)32位的2進(jìn)制數(shù)想暗,所能代表的數(shù)字范圍是【-2^n~2^(n-1)-1】超出這個(gè)范圍時(shí)表示“溢出”,超過上限值叫做“上溢出”帘不,超過下限值叫做“下溢出”说莫。溢出的部分采用了數(shù)學(xué)中的余數(shù)思想和同余定理來處理。例如:int最大值2^(n-1)-1最高位是0寞焙,其余位都是1储狭,如果再加個(gè)1,則發(fā)生上溢出捣郊,此時(shí)的二進(jìn)制數(shù)為最高位為1辽狈,其余位為0,即int的最小值呛牲。因此“上溢出”后的值又開始從最小到最大周而復(fù)始的變化刮萌,這說明數(shù)據(jù)“溢出”時(shí)的處理方式正是余數(shù)思想,其中取余的除數(shù)為最大值減去最小值+1娘扩,即[(2^(n-1)-1) - (-2^(n-1))+1 =2^(n-1) +1]着茸。
二進(jìn)制的原碼、反碼琐旁、補(bǔ)碼的意義涮阔?
????????由于計(jì)算機(jī)在設(shè)計(jì)之初只實(shí)現(xiàn)了加法器,因此如果想讓負(fù)數(shù)也支持加法運(yùn)算灰殴,或者說讓計(jì)算機(jī)支持減法運(yùn)算敬特,得統(tǒng)一正數(shù)和負(fù)數(shù)的二進(jìn)制計(jì)算形式。二進(jìn)制數(shù)最終都是以補(bǔ)碼形式進(jìn)行加減計(jì)算的牺陶。正數(shù)的補(bǔ)碼與原碼伟阔、反碼一樣;負(fù)數(shù)的反碼等于去除符號(hào)位掰伸,其余按位取反皱炉,負(fù)數(shù)的補(bǔ)碼等于反碼加一。例如:有符號(hào)二進(jìn)制數(shù)10100010對應(yīng)的十進(jìn)制數(shù)是多少碱工?(-94)
????????方法一:先求補(bǔ)碼娃承,再針對補(bǔ)碼除符號(hào)位外奏夫,進(jìn)行按位加權(quán)求和,再取反历筝。
????????方法二:原碼除符號(hào)位外酗昼,進(jìn)行按位加權(quán)求和,減去(2^n-1+1)梳猪。
????????方法三:反碼除符號(hào)位外麻削,其余各位按位加權(quán)求和+1后,取反春弥。
二進(jìn)制的位(位移呛哟、按位邏輯)運(yùn)算
? ? ?????位移運(yùn)算:
? ? ????????????<<:帶符號(hào)左移,低位補(bǔ)0匿沛。
? ????? ????????>>:帶符號(hào)右移扫责,符號(hào)位為1時(shí),說明是負(fù)數(shù)逃呼,符號(hào)位不變鳖孤,高位補(bǔ)1;符號(hào)位為0時(shí)抡笼,說明是正數(shù)苏揣,高位補(bǔ)0。
? ????? ????????>>>:無符號(hào)右移推姻,高位補(bǔ)0平匈。
? ? ? ? ?值得關(guān)注的是:
? ? ? ? ? ? ? ? 位移操作時(shí)二進(jìn)制的位數(shù)超過了系統(tǒng)指定的位數(shù)時(shí),會(huì)發(fā)生數(shù)據(jù)溢出藏古,溢出的位數(shù)直接舍去增炭;(比如:一個(gè)32位的二進(jìn)制數(shù)正數(shù),發(fā)生左移或右移1位時(shí)校翔,左邊和右邊的第一位都會(huì)因溢出而直接舍去弟跑,然后再在低位和高位補(bǔ)0)??在未發(fā)生數(shù)據(jù)溢出時(shí),<<n相當(dāng)于乘以2^n倍防症,>>n近似相當(dāng)于除以2^n倍。
? ? ? ? ? ? ? ? 位移運(yùn)算僅作用于整數(shù)(32位)和長整數(shù)(64位)數(shù)上哎甲,假如在整型數(shù)上移動(dòng)32位蔫敲,無論是否帶符號(hào)以及方向,均為本身炭玫。因?yàn)橐苿?dòng)的位數(shù)是個(gè)mod 32的結(jié)果奈嘿,4>>>1和4>>>33是一個(gè)結(jié)果。負(fù)數(shù)在無符號(hào)右移63位時(shí)吞加,除了當(dāng)前位為1裙犹,之前的位均為0尽狠,達(dá)到最小值1,如果>>>64叶圃,則為其原值本身袄膏。
? ? ? ? ?按位邏輯運(yùn)算:
? ? ????????????按位與&:參與操作的位中必須全部為1,結(jié)果才是1掺冠,否則就是0沉馆。
? ? ????????????按位或|:參與操作的位中只要有一個(gè)是1,結(jié)果就是1德崭。
? ? ????????????按位異或^:參與操作的位中必須不同斥黑,結(jié)果才為1,否則為0眉厨。(相等的兩個(gè)數(shù)異或結(jié)果為0锌奴,任意一個(gè)數(shù)的二進(jìn)制數(shù)異或0的結(jié)果都是這個(gè)數(shù)本身)
? ? ? ? ?二進(jìn)制按位操作的意義:直接操作內(nèi)存,效率高憾股。
位運(yùn)算應(yīng)用場景
????????IP地址與整數(shù)互換:在實(shí)際工作中會(huì)有統(tǒng)計(jì)IP出現(xiàn)次數(shù)的需求鹿蜀。通常會(huì)存儲(chǔ)在HashMap中,以IP地址作為Map的Key,累計(jì)出現(xiàn)的次數(shù)作為Map的Value荔燎。但I(xiàn)P字符串所占的字節(jié)數(shù)會(huì)比其對應(yīng)的整數(shù)(32bit)占用更多內(nèi)存耻姥,因此將IP地址轉(zhuǎn)化成整數(shù)值作為key,會(huì)大大減少HashMap的實(shí)際存儲(chǔ)容量有咨。
????????????????IP地址—>長整型數(shù)
????????????? ? ? ? ? ?*方法1:“5,3,12,1”的IP地址琐簇,由4段10進(jìn)制整數(shù)構(gòu)成,每段IP的取值范圍是0-255(2^8)之間座享,由此可以把這個(gè)點(diǎn)分IP地址表示為一個(gè)32位二進(jìn)制數(shù)婉商,每個(gè)IP段對應(yīng)這個(gè)32位二進(jìn)制的高24位、高16位渣叛、高8位和低8位丈秩。對這個(gè)32位二進(jìn)制數(shù)從低位到高位使用二進(jìn)制加權(quán)求和。
????????????????????????result = 1*2^0+1*2^10+1*2^11+1*2^16+1*2^17+1*2^24
? ? ? ? ? ? ? ? ? ? ? ? ? ????????=1+2^8*4+2^8*8+2^8*256+2^8*512+2^8*256*256+1*2^26
? ? ? ? ? ? ? ? ? ? ? ? ? ????????=84085761L淳衙。
? ? ? ? ? ? ? ? ????????方法2:將IP看成是一個(gè)2^8即256進(jìn)制表示的數(shù)蘑秽,每一位相當(dāng)于對256取余的結(jié)果。
? ? ? ? ? ? ? ? ? ? ????如果用10進(jìn)制表示法箫攀,來表示一個(gè)數(shù)時(shí)
????????????????????????53121= 5*10^4+3*10^3+1*10^2+2*10^1+1*10^0肠牲,
? ? ? ? ? ? ? ? ? ? ????那么根據(jù)10進(jìn)制表示法推導(dǎo)256進(jìn)制表示法
? ? ? ? ? ? ? ? ? ? ????result = 5*(2^8)^3 + 3*(2^8)^2+12*(2^8)^1+1*(2^8)^0
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? =5*256^3+3*256^2+12*256^1+1*256^0
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? =83886080+196608+3072+1=84085761L
? ? ? ? ? ? ? ? ? ? ? ? *方法3:將IP看做4段8位二進(jìn)制數(shù),進(jìn)行了位移操作的結(jié)果靴跛。其中第一段IP算術(shù)左移了24位缀雳,第二段IP算術(shù)左移了16位,第三段IP算術(shù)左移了8位梢睛,第四段IP未進(jìn)行位移操作(算術(shù)左移<<操作肥印,在沒有發(fā)生數(shù)據(jù)溢出時(shí)识椰,<<n 相當(dāng)于對當(dāng)前10進(jìn)制數(shù)擴(kuò)大了2^n倍)。
? ? ? ? ? ? ? ? ?????????result =5<<24+3<<16+12<<8+1?
? ? ? ? ? ? ? ? ? ? ? ? ? ?????????= 5*2^24+3*2^16+12*2^8+1?
? ? ? ? ? ? ? ? ? ? ? ? ? ?????????=84085761L
? ? ? ? ?????????長整型數(shù)—>IP地址:(長整型在位移之前先轉(zhuǎn)化為對應(yīng)的點(diǎn)分32位二進(jìn)制形式深碱,即00000101.00000011.00001100.00000001)
? ? ? ? ????????????1侵状、將長整型數(shù)>>>24位僻弹,高位補(bǔ)0忽匈,即得第一段IP值鞠值。
? ? ? ? ????????????2、將長整型數(shù)前8位&0即將高8位設(shè)為0竞膳,再>>>16航瞭,高位補(bǔ)0,即得第二段IP值3坦辟。
? ? ? ? ? ? ? ? ????即 : 00000101.00000011.00001100.00000001 & 0x00FFFFFF —>
? ????????????????????????00000000.00000011.00001100.00000001 (高位設(shè)為0)刊侯,然后再>>>16,?—>
? ????????????????????????00000000.00000000.00000000.00000011(3)
? ? ? ? ????????????3锉走、將長整型數(shù)前16位&0即將高16位設(shè)為0滨彻,再>>>8,高位補(bǔ)0挪蹭,即得第三段IP值亭饵。
? ??????? ? ? ? ????4、將長整型數(shù)前24位&0即將高24位設(shè)為0梁厉,即得第四段IP值辜羊。
? ? ? ? ? ? ? ? ????5、將所得的四段IP值词顾,使用StringBuilder拼接成完整IP地址八秃。
? ? ? ? 十進(jìn)制轉(zhuǎn)二進(jìn)制
? ? ? ? 如果decimalSource為負(fù)數(shù)-25肉盹,則其二進(jìn)制是其正數(shù)取補(bǔ)的結(jié)果 昔驱。
? ? ? ? 例如:25對應(yīng)的二進(jìn)制原碼為 00011001,
? ? ? ? ? ? ? ? ? 反碼:11100110(原碼按位取反)
? ? ? ? ? ? ? ? ? 補(bǔ)碼:11100111(反碼+1)
? ? ? ? ? ? ? ? ? -25(10)—>11100111(2)
????????奇偶數(shù)校驗(yàn):偶數(shù)的二進(jìn)制最后一位總是0上忍,奇數(shù)的二進(jìn)制數(shù)總是1骤肛。基于這個(gè)特點(diǎn)窍蓝,讓一個(gè)數(shù)&1操作萌衬,代替取余,進(jìn)行奇偶數(shù)判斷它抱。1的二進(jìn)制數(shù)最后一位是1,其余位均為0朴艰。因此任意一個(gè)奇數(shù)&1的結(jié)果為1观蓄,偶數(shù)&1結(jié)果為0混移。例如:(5&1 = 0101&0001=0001=1;2&1=0010&0001=0000=0)
????????兩數(shù)相等判斷:相等的兩個(gè)數(shù)按位異或結(jié)果為0侮穿,即x^x=0歌径。
? ? ? ? 兩數(shù)交換:使用異或操作實(shí)現(xiàn)性能高效,減少臨時(shí)變量的使用亲茅。
????????哈希取余:如果a%b回铛,b=2^n。則a%b=a&(b-1)克锣。
總結(jié)
????????計(jì)算機(jī)只能處理0或1的二進(jìn)制數(shù)據(jù)茵肃,二進(jìn)制數(shù)以補(bǔ)碼的形式進(jìn)行加減運(yùn)算;位移運(yùn)算只發(fā)生在整型和長整型的二進(jìn)制數(shù)中袭祟。因?yàn)槊糠N數(shù)據(jù)類型有各自的取值范圍验残,因此在進(jìn)行數(shù)據(jù)加減或位移運(yùn)算時(shí)均會(huì)發(fā)生數(shù)據(jù)溢出,溢出時(shí)采用余數(shù)思想進(jìn)行處理巾乳。
? ? ? ? 加減運(yùn)算本質(zhì)就是兩數(shù)和您没,mod這個(gè)除數(shù)的結(jié)果,而除數(shù)就是當(dāng)前數(shù)據(jù)類型最大值減去最小值+1胆绊;而移位運(yùn)算移動(dòng)的位數(shù)本質(zhì)也是將當(dāng)前數(shù)據(jù)類型長度作為除數(shù)(int為32)氨鹏,使用二進(jìn)制要移動(dòng)的位數(shù)mod這個(gè)除數(shù)的結(jié)果。
? ? ? ? 二進(jìn)制數(shù)除了加減運(yùn)算压状、位移運(yùn)算外還支持按位邏輯運(yùn)算(按位與&仆抵、按位或|、按位非^何缓、按位取反~)肢础。利用二進(jìn)制位操作可:簡化復(fù)雜哈希取余運(yùn)算、實(shí)現(xiàn)奇偶數(shù)校驗(yàn)碌廓、兩數(shù)相等判斷以及IP與整數(shù)互換等功能传轰。