真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Kotlin基礎(chǔ)學(xué)習(xí)之位運(yùn)算

什么是位運(yùn)算?

創(chuàng)新互聯(lián)專注于企業(yè)營(yíng)銷(xiāo)型網(wǎng)站、網(wǎng)站重做改版、雨城網(wǎng)站定制設(shè)計(jì)、自適應(yīng)品牌網(wǎng)站建設(shè)、成都h5網(wǎng)站建設(shè)、電子商務(wù)商城網(wǎng)站建設(shè)、集團(tuán)公司官網(wǎng)建設(shè)、成都外貿(mào)網(wǎng)站制作、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁(yè)設(shè)計(jì)等建站業(yè)務(wù),價(jià)格優(yōu)惠性價(jià)比高,為雨城等各大城市提供網(wǎng)站開(kāi)發(fā)制作服務(wù)。

程序中的所有數(shù)在計(jì)算機(jī)內(nèi)存中都是以二進(jìn)制的形式儲(chǔ)存的。位運(yùn)算說(shuō)穿了,就是直接對(duì)整數(shù)在內(nèi)存中的二進(jìn)制位進(jìn)行操作。比如,and運(yùn)算本來(lái)是一個(gè)邏輯運(yùn)算符,但整數(shù)與整數(shù)之間也可以進(jìn)行and運(yùn)算。舉個(gè)例子,6的二進(jìn)制是110,11的二進(jìn)制是1011,那么6 and 11的結(jié)果就是2,它是二進(jìn)制對(duì)應(yīng)位進(jìn)行邏輯運(yùn)算的結(jié)果(0表示False,1表示True,空位都當(dāng)0處理):

110
AND 1011
———-
0010 –> 2

由于位運(yùn)算直接對(duì)內(nèi)存數(shù)據(jù)進(jìn)行操作,不需要轉(zhuǎn)成十進(jìn)制,因此處理速度非???。當(dāng)然有人會(huì)說(shuō),這個(gè)快了有什么用,計(jì)算6 and 11沒(méi)有什么實(shí)際意義啊。這一系列的文章就將告訴你,位運(yùn)算到底可以干什么,有些什么經(jīng)典應(yīng)用,以及如何用位運(yùn)算優(yōu)化你的程序。

引言

這個(gè)還真是基礎(chǔ)中的基礎(chǔ),如果你跟我一樣之前沒(méi)有好好學(xué)習(xí)過(guò)Java基礎(chǔ)語(yǔ)法,這塊對(duì)你來(lái)說(shuō)應(yīng)該是一個(gè)懵逼點(diǎn)吧。不談底層什么的,單單從android編程來(lái)看,我們?cè)诩用芩惴ㄟ€有網(wǎng)絡(luò)包處理等業(yè)務(wù)上使用位運(yùn)算的頻率還是很高的,更別提Intent中的那些種類(lèi)繁多的Flag了,因此學(xué)好這方面的基礎(chǔ)知識(shí)還是很重要的

本系列的例子使用的是Kotlin的語(yǔ)法,跟Java相比還是有所區(qū)別,請(qǐng)對(duì)照參考

無(wú)符號(hào)和有符號(hào)

在計(jì)算機(jī)中,可以區(qū)分正負(fù)的類(lèi)型稱為有符號(hào)類(lèi)型,沒(méi)有正負(fù)類(lèi)型的稱為無(wú)符號(hào)類(lèi)型。

一個(gè)字節(jié)為8位,從0開(kāi)始算,那它的最高位就是第7位。同樣2個(gè)字節(jié)最高位為第15位,4個(gè)字節(jié)最高位為第31位。不同長(zhǎng)度的類(lèi)型,最高位不同,但是都是最左邊的那個(gè)。

無(wú)符號(hào)數(shù)中,所有的位都用于直接表示該值的大小;有符號(hào)數(shù)中最高位用于表示正負(fù),0表示正數(shù),1表示負(fù)數(shù)。因此同樣一個(gè)字節(jié),無(wú)符號(hào)數(shù)最大值為255,有符號(hào)數(shù)最大值為127。有符號(hào)數(shù)最大值計(jì)算完全跟無(wú)符號(hào)數(shù)一樣,但是在負(fù)數(shù)范圍內(nèi)就不能用剛才那種計(jì)算方式了,在計(jì)算機(jī)中,負(fù)數(shù)除了最高位為1以外,還采用補(bǔ)碼的形式,所以在計(jì)算中要對(duì)補(bǔ)碼進(jìn)行還原

值得注意:的是JAVA的原始類(lèi)型里沒(méi)有無(wú)符號(hào)整型,如果需要轉(zhuǎn)成無(wú)符號(hào)類(lèi)型,可以用ushr

原碼、補(bǔ)碼、反碼

這個(gè)是高中就教過(guò)的知識(shí),這里就不再做介紹

提醒一下,負(fù)數(shù)都是用補(bǔ)碼參與運(yùn)算的,得到的也是補(bǔ)碼,需要減1取反獲得原碼。

位運(yùn)算符

位運(yùn)算主要在直接操控二進(jìn)制數(shù)時(shí)進(jìn)行使用,可以達(dá)到節(jié)約內(nèi)存,使你的程序運(yùn)行速度更快

Java定義了位運(yùn)算符,可應(yīng)用在整形(int)、長(zhǎng)整型(long)、短整型(short)以及字符型(byte)等類(lèi)型上。位運(yùn)算符作用在所有的位上,并按位進(jìn)行運(yùn)算。Kotlin與之略有不同,它并沒(méi)有提供特殊的操作符,只提供了中綴形式的表示方法,并且Kotlin只可用在Int和Long類(lèi)型上,這點(diǎn)千萬(wàn)要記住

咱們來(lái)看一個(gè)例子

 val a1 = 60
 val b1 = 13
 var c1 = -5
 // 與
 println(a1 and b1)
 // 或
 println(a1 or b1)
 // 異或
 println(a1 xor b1)
 // 按位取反
 println(a1.inv())
 // 左移
 println(a1.shl(1))
 // 右移
 println(a1.shr(1))
 // 無(wú)符號(hào)右移
 println(a1.ushr(1))

先看看結(jié)果,然后我們?cè)僖粋€(gè)個(gè)的分析

12
61
49
-61
120
30
30

我們知道,Java中的Int是4個(gè)字節(jié)32位的,那么a1與b1、c1轉(zhuǎn)換成二進(jìn)制就應(yīng)該是

val a1 = 60 // 0000 0000 0000 0000 0000 0000 0011 1100
val b1 = 13 // 0000 0000 0000 0000 0000 0000 0000 1101
var c1 = -5 // 1111 1111 1111 1111 1111 1111 1111 1011

隨后就是7種中綴表達(dá)式的計(jì)算規(guī)則

and 如果對(duì)應(yīng)位都是1,則結(jié)果為1,否則為0

or 如果對(duì)應(yīng)位都是0,則結(jié)果為0,否則為1

xor 如果對(duì)應(yīng)位值相同,則結(jié)果為0,否則為1

inv 按位翻轉(zhuǎn)操作數(shù)的每一位,即0變成1,1變成0

shl 按位左移指定的位數(shù),相當(dāng)于乘以2的N次方。移掉的省略,右邊缺失的位,用0補(bǔ)齊

shr 按位右移指定的位數(shù),相當(dāng)于除以2的N次方,移掉的省略,左邊缺失的位,如果是正數(shù)則補(bǔ)0,若為負(fù)數(shù),可能補(bǔ)0或補(bǔ)1,這取決于所用的計(jì)算機(jī)系統(tǒng)

ushr 按位右移指定的位數(shù),移掉的省略,左邊缺失的位,用0補(bǔ)齊

所以我們來(lái)看看按位計(jì)算的結(jié)果(省略掉高位重復(fù)的0或者1,只看低八位)

通過(guò)上述規(guī)則,我們就能明白計(jì)算結(jié)果是怎樣得到的

“與”的結(jié)果就是00001100,即為12
“或”的結(jié)果就是00111101,即為61
“異或”的結(jié)果就是00110001,即為49
“非a1”的結(jié)果就是11000011,即為-61
“左移a1 1位”的結(jié)果就是01111000,即為120
“右移a1 1位”的結(jié)果就是00011110,即為30
“無(wú)符號(hào)右移a1 1位”的結(jié)果就是00011110,即為30

有一個(gè)很有趣的現(xiàn)象,對(duì)于一個(gè)Int類(lèi)型的數(shù)值,無(wú)論你執(zhí)行左移還是右移還是無(wú)符號(hào)右移,只要移動(dòng)32位,效果跟沒(méi)有移動(dòng)一致。這是因?yàn)樵贘AVA進(jìn)行移位運(yùn)算中因?yàn)镮nt是占32位,進(jìn)行移位的數(shù)就是32的模,所以當(dāng)數(shù)值移動(dòng)32位的時(shí)候就等于數(shù)值移動(dòng)0位,也相當(dāng)于沒(méi)有進(jìn)行移位。同理Long類(lèi)型的移位,Long占8字節(jié)也就是64位,所以移位的數(shù)是64的模

應(yīng)用舉例

有一個(gè)位運(yùn)算口訣大家可以記一下:

清零取反要用與,某位置一可用或

若要取反和交換,輕輕松松用異或

判斷Int型變量a是奇數(shù)還是偶數(shù)

a1 and 1 = 0 // 偶數(shù)
a1 and 1 = 0 // 奇數(shù)

獲取Int型變量的第K位(注:K從0開(kāi)始依次由右往左,以下揭同)

a1 shr k and 1

將Int型變量的第K位清0

a1 and ((1 shl k).inv())

將Int型變量的第K位置1

a1 or (1 shl k)

平均值

(a1 and b1)+((a1 xor b1) shr 1)

不用temp交換兩個(gè)整數(shù)

a1 = a1 xor b1
b1 = b1 xor a1
a1 = a1 xor b1

獲取絕對(duì)值

val temp = c1 shr 31
(c1 + temp) xor temp
(c1 xor temp) - temp

獲取相反數(shù)

c1.inv()+1

Int轉(zhuǎn)byte數(shù)組

val bytes = ByteArray(4)
bytes[0] = (a1 and 0xFF).toByte()
bytes[1] = (a1 shr 8 and 0xFF).toByte()
bytes[2] = (a1 shr 16 and 0xFF).toByte()
bytes[3] = (a1 shr 24 and 0xFF).toByte()

補(bǔ)零擴(kuò)展和補(bǔ)符號(hào)位擴(kuò)展

在看這個(gè)問(wèn)題之前,我們先做一個(gè)小游戲

val byte1: Byte = -127
println(byte1)
println(byte1.toInt())
println(byte1.toInt() and 0xff)

看官請(qǐng)猜猜看呢

還是我來(lái)公布答案吧

-127
-127
129

能解釋一下為什么-127變成129嗎?這個(gè)就牽扯到補(bǔ)零擴(kuò)展和補(bǔ)符號(hào)位擴(kuò)展了

之前我們知道,Java是沒(méi)有無(wú)符號(hào)類(lèi)型的,byte是8個(gè)字節(jié)而int是32個(gè)字節(jié)。在byte轉(zhuǎn)int的時(shí)候,肯定要將8位補(bǔ)到32位。Java中的擴(kuò)展方式是補(bǔ)符號(hào)位擴(kuò)展,所以-127通過(guò)補(bǔ)符號(hào)位擴(kuò)展之后還是-127,即11111111 11111111 11111111 10000001。如果采用補(bǔ)零擴(kuò)展,相當(dāng)于11111111 11111111 11111111 10000001 and 11111111,這個(gè)值就是00000000 00000000 00000000 10000001,也就是129了

為了加深記憶,我再留一道題給大家思考

println(0x100000000L + 0xcafebabe.toInt())
println(0x100000000L + 0xcafebabeL)

這兩個(gè)表達(dá)式打印出來(lái)也不一樣,現(xiàn)在你應(yīng)該能明白為什么不一樣了吧

總結(jié)一下

Java中只有有符號(hào)數(shù)。當(dāng)byte擴(kuò)展到short,int時(shí),因?yàn)榉?hào)位是0,所以正數(shù)都一樣,無(wú)論如何都是補(bǔ)零擴(kuò)展;但負(fù)數(shù)補(bǔ)零擴(kuò)展和按符號(hào)位擴(kuò)展結(jié)果完全不同。

補(bǔ)符號(hào)位擴(kuò)展,原數(shù)值不變。補(bǔ)零擴(kuò)展,相當(dāng)于把有符號(hào)數(shù)看成無(wú)符號(hào)數(shù)。

對(duì)于有符號(hào)數(shù),默認(rèn)采用符號(hào)位擴(kuò)展。由小擴(kuò)展到大時(shí),需要用and 0xff這樣方式來(lái)確保是按補(bǔ)零擴(kuò)展的;而從大向小時(shí),符號(hào)位自動(dòng)無(wú)效,所以不用處理。如果是char類(lèi)型,那么不管它將要被擴(kuò)展成什么類(lèi)型,都執(zhí)行補(bǔ)零擴(kuò)展

參考文章

  • Java的移位操作(收集+糾正)
  • 淺談Java中的補(bǔ)零擴(kuò)展和補(bǔ)符號(hào)位擴(kuò)展
  • java中的有符號(hào),無(wú)符號(hào)操作以及DataInputStream

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)創(chuàng)新互聯(lián)的支持。


本文題目:Kotlin基礎(chǔ)學(xué)習(xí)之位運(yùn)算
地址分享:http://weahome.cn/article/gicooh.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部