新聞中心
go語(yǔ)言操作符 ^ 和 &^
很多語(yǔ)言都是采用 ~ 作為按位取反運(yùn)算符,Go 里面采用的是 ^ 。
公司主營(yíng)業(yè)務(wù):成都網(wǎng)站建設(shè)、成都做網(wǎng)站、移動(dòng)網(wǎng)站開發(fā)等業(yè)務(wù)。幫助企業(yè)客戶真正實(shí)現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競(jìng)爭(zhēng)能力。成都創(chuàng)新互聯(lián)是一支青春激揚(yáng)、勤奮敬業(yè)、活力青春激揚(yáng)、勤奮敬業(yè)、活力澎湃、和諧高效的團(tuán)隊(duì)。公司秉承以“開放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對(duì)我們的高要求,感謝他們從不同領(lǐng)域給我們帶來(lái)的挑戰(zhàn),讓我們激情的團(tuán)隊(duì)有機(jī)會(huì)用頭腦與智慧不斷的給客戶帶來(lái)驚喜。成都創(chuàng)新互聯(lián)推出安義免費(fèi)做網(wǎng)站回饋大家。
如果作為二元運(yùn)算符,^ 表示按位異或,即:對(duì)應(yīng)位相同為 0,相異為 1。
操作符 ^,按位置零,例如:z = x ^ y,表示如果 y 中的 bit 位為 1,則 z 對(duì)應(yīng) bit 位為 0,否則 z 對(duì)應(yīng) bit 位等于 x 中相應(yīng)的 bit 位的值。
對(duì)于有符號(hào)的整數(shù)來(lái)說(shuō),是按照補(bǔ)碼進(jìn)行取反操作的(快速計(jì)算方法:對(duì)數(shù) a 取反,結(jié)果為 -(a+1) ),對(duì)于無(wú)符號(hào)整數(shù)來(lái)說(shuō)就是按位取反
計(jì)算過程
以3為例? 3在內(nèi)存中補(bǔ)碼為 0*** 0011
取反? ? ? ? ? ? 1*** 1100
-1操作? ? ? ? ? 1*** 1011
除符號(hào)位取反? ? 1*** 0100 結(jié)果為-4
-------------------------------------------
以9為例 9在內(nèi)存中補(bǔ)碼為 0*** 1001
取反? ? ? ? ? ? 1*** 0110
-1操作? ? ? ? ? 1*** 0101
除符號(hào)位取反? ? 1*** 1010 結(jié)果為-10
-------------------------------------------
以-5為例 -5在內(nèi)存中為的補(bǔ)碼為 1*** 1011
為什么呢
-5源碼? ? ? ? ? 1*** 0101
除符號(hào)取反? ? ? 1*** 1010
+1操作? ? ? ? ? 1*** 1011
-------------------------------------------
那么-5取反怎么算
補(bǔ)碼 1***1011取反為 0***0100
因?yàn)榉?hào)位為0,所以是正數(shù)了,正數(shù)的補(bǔ)碼反碼源碼都是一個(gè),所以是4
===================================
再看-1
-1源碼? ? ? ? ? 1*** 0001
除符號(hào)取反? ? ? 1*** 1110
+1操作? ? ? ? ? 1*** 1111
補(bǔ)碼 1*** 1111 取反為 0*** 0000
因?yàn)榉?hào)位為0,所以是正數(shù)了,正數(shù)的補(bǔ)碼反碼源碼都是一個(gè),所以是0
go語(yǔ)言取反輸出的例子看這里
golang 正負(fù)數(shù)取反
想要知道取反計(jì)算過程,首先搞懂? “原碼“,“反碼”,“補(bǔ)碼”,“取反”。
0變1,1變0
原碼是計(jì)算機(jī)機(jī)器數(shù)中最簡(jiǎn)單的一種形式,數(shù)值位就是真值的絕對(duì)值。原碼表示法在最高位為符號(hào):正數(shù)該位為0,負(fù)數(shù)該位為1,原碼又稱帶符號(hào)的絕對(duì)值。看整數(shù)9及-9的原碼如下:
9的原碼:0000 1001
-9的原碼: 1000 1001
重點(diǎn):對(duì)于源碼,絕對(duì)值相等的正數(shù)和負(fù)數(shù)只有符號(hào)位不同。
反碼通常是用來(lái)由原碼求補(bǔ)碼或者由補(bǔ)碼求原碼的過渡碼。正數(shù)的反碼就是其原碼,負(fù)數(shù)的反碼就是將原碼除符號(hào)位以外每位取反(0變1,1變0)。例如:
9的反碼:0000 1001
-9的反碼:1111 0110
在計(jì)算機(jī)系統(tǒng)中,數(shù)值一律用補(bǔ)碼來(lái)表示和存儲(chǔ)。正數(shù)的原碼就是其補(bǔ)碼。負(fù)數(shù)的補(bǔ)碼是其反碼+1.例如:
9的補(bǔ)碼:0000 1001
-9的補(bǔ)碼:1111 0111
正整數(shù)的原碼、反碼、補(bǔ)碼都是一樣的。負(fù)數(shù)的反碼是除符號(hào)位其他每一位取反,負(fù)數(shù)的補(bǔ)碼是其反碼+1
首先明確一個(gè)概念,由于在計(jì)算機(jī)中二進(jìn)制都是以其補(bǔ)碼形式存放在內(nèi)存中的。所以要知道 ^9 就是對(duì) 9 的補(bǔ)碼取反,也就是說(shuō)無(wú)論是整數(shù)還是負(fù)數(shù)對(duì)其取反都是對(duì)其補(bǔ)碼取反。
正數(shù)9:
原碼為: 0000 1001
反碼為: 0000 1001
補(bǔ)碼為: 0000 1001
1. 取反結(jié)果=負(fù)數(shù)補(bǔ)碼 :0000 1001 --- (取反) 1111 0110?
注:由于 ^ 位取反操作符,對(duì)于符號(hào)位也會(huì)取反 所以這里得到一個(gè)負(fù)數(shù)的補(bǔ)碼,想要計(jì)算其真實(shí)的值。還需要將其轉(zhuǎn)換成原碼。
2. 得反碼:1111 0110? -? 1? =??1111 0101
補(bǔ)碼 = 反碼 + 1 (反推) 反碼?= 補(bǔ)碼 - 1
3. 得原碼?1111 0101 -- 1111 1010 = -10
原碼? =? 反碼取反
負(fù)數(shù)-9:
原碼為: 1111 1001
反碼為: 1111 0110
補(bǔ)碼為: 1111 0111
1. 取反結(jié)果=正數(shù)補(bǔ)碼?1111 0111 ----?0000 1000
2. 正數(shù)原碼 = 反碼 = 補(bǔ)碼 =?0000 1000 = 8
>> 0 談?wù)?js 中的位運(yùn)算'>js >>> 0 談?wù)?js 中的位運(yùn)算
這不就是無(wú)符號(hào)右移嘛,當(dāng)時(shí)第一感覺是是為了取絕對(duì)值,后來(lái)發(fā)現(xiàn)并不是,嘗試了多次之后,發(fā)現(xiàn)情況有點(diǎn)詭異啊,我們使用 chrome 調(diào)試工具運(yùn)行一下 js 中的無(wú)符號(hào)右移 0 位。
不僅是 null 無(wú)符號(hào)右移會(huì)變成 0 , js 中的其他非數(shù)值做此運(yùn)算都會(huì)變成 0 。
接下來(lái)我們來(lái)看看為什么會(huì)這樣(事實(shí)上不僅僅只是無(wú)符號(hào)右移是這樣)。要理解這個(gè)問題需要先明白什么是位運(yùn)算以及為什么需要位運(yùn)算,然后搞明白 js 中的位運(yùn)算有什么特別之處。
敬請(qǐng)期待
(這一部分我是拿 java、go 與 js 做對(duì)比的。)
這在 java、go、c 中都是不被允許的
細(xì)心的人已經(jīng)發(fā)現(xiàn),基本類型里并沒有浮點(diǎn)型。
事實(shí)上在 js 中的 Number 類型是不區(qū)分 int、long、float、double 類型的( go 的用戶們就呵呵一笑了,來(lái)來(lái)來(lái),我們的浮點(diǎn)型就能王炸你)。回正題,不區(qū)分整型、浮點(diǎn)型那怎么存儲(chǔ)呢,為了不丟失精度, js 中的 Number 類型實(shí)際上一個(gè)基于 IEEE 754 標(biāo)準(zhǔn)的雙精度64位浮點(diǎn)數(shù)( java 的同學(xué)就把它當(dāng)成 double 看)。看到這我想很多人應(yīng)該能明白為什么 js 里浮點(diǎn)數(shù)也能參與位運(yùn)算了吧。這也是沒有辦法,因?yàn)閷?duì)于內(nèi)存來(lái)說(shuō)整型、浮點(diǎn)型都沒有區(qū)別了。
這里是有一個(gè)問題的,因?yàn)楫?dāng) js 需要進(jìn)行位運(yùn)算時(shí),會(huì)將操作數(shù)通通轉(zhuǎn)成 32 位比特序列(0,1),也就是補(bǔ)碼。操作完成之后,再按照 64 位浮點(diǎn)數(shù)存儲(chǔ)
直接丟棄!!! 曾吶!這么虎?
沒錯(cuò),就是這么暴力,那么問題來(lái)了,既然小數(shù)部分不參與位運(yùn)算,那么為什么不能像 java、go 那樣直接禁止呢?關(guān)于這個(gè)問題,我想那就是語(yǔ)言設(shè)計(jì)者的想法,我就不知道了。但是這其實(shí)也帶來(lái)了一些特別的操作,比如在 js 中雙取反是可以做取整操作的。
當(dāng) js 需要進(jìn)行位運(yùn)算的時(shí)候,對(duì)于非數(shù)值類型,會(huì)首先將操作數(shù)轉(zhuǎn)成一個(gè)整型(就是0)然后在進(jìn)行運(yùn)算。這就解釋了為什么 js 中可以允許非數(shù)值類型參與運(yùn)算,其實(shí)這是個(gè)偽命題,因?yàn)閷?shí)質(zhì)上是對(duì)非數(shù)值操作數(shù)的整型表達(dá)式進(jìn)行的位運(yùn)算。
這里需要注意,上面說(shuō)過了 js 中的整型在內(nèi)存中都是一個(gè) 64 位雙精度浮點(diǎn)型,但是 js 進(jìn)行位運(yùn)算時(shí),會(huì)將操作數(shù)轉(zhuǎn)成帶符號(hào)位的 32 位比特序列(0,1),也就是補(bǔ)碼。運(yùn)算結(jié)束后,再按照 64 位存儲(chǔ)。那么問題來(lái)了,這里肯定會(huì)存在精度丟失對(duì)吧,這應(yīng)該不難理解。 js 確實(shí)也是這樣處理的,超過 32 位的部分直接截?cái)唷?/p>
所以對(duì)一個(gè)非數(shù)值變量做取反操作,得到的一定是 -1,因?yàn)閷?shí)際上等于對(duì) 0 做取反操作。
首尾呼應(yīng)一下,畢竟就是這個(gè)問題使我查資料寫了這篇文章。
首先解釋一下, 無(wú)符號(hào)右移原本是 java 里特有的(這里是和 js、go 對(duì)比,其他語(yǔ)言我沒用過,不能亂說(shuō))。 js 中的無(wú)符號(hào)右移跟 java 幾乎一樣,除了一點(diǎn)兩種語(yǔ)言處理方式完全不一樣。
那就是并沒有真正發(fā)生移位的情況下,符號(hào)位會(huì)不會(huì)被替換成0。 java 中是不會(huì)替換的,但是 js 中是會(huì)發(fā)生替換的。
當(dāng)操作數(shù)是正數(shù)的時(shí)候,不管有沒有真的移位并沒有區(qū)別,因?yàn)檎龜?shù)的符號(hào)位是 0。
當(dāng)操作數(shù)是負(fù)數(shù)時(shí),移動(dòng)位數(shù)大于0,也體現(xiàn)不出區(qū)別:
但是當(dāng)操作數(shù)是負(fù)數(shù),無(wú)符號(hào)右移 0 位時(shí),區(qū)別就大了:
這是因?yàn)?-1 的補(bǔ)碼是:
0 實(shí)際上并沒有發(fā)生數(shù)位變化,但是 js 卻會(huì)把符號(hào)位替換成 0,
此時(shí)原來(lái)負(fù)數(shù)的補(bǔ)碼,變?yōu)榱苏龜?shù)的源碼(這就是為什么 js 中 -10 會(huì)變成一個(gè)巨大的正整數(shù))。
js 中無(wú)符號(hào)右移時(shí),不管正數(shù)、負(fù)數(shù)都會(huì)首先將符號(hào)位替換成 0,然后再進(jìn)行移位。也就是說(shuō),該運(yùn)算符永遠(yuǎn)返回正整數(shù)。
js 的位運(yùn)算,為什么會(huì)有這么多奇怪的地方呢?我相信很多同學(xué)都會(huì)有這種想法,特別是 java 的同學(xué)們吧。為此我查了 js 的歷史。
1995 Sun 公司正式發(fā)布 java 語(yǔ)言,當(dāng)時(shí)的網(wǎng)景公司正在為它們的 Navigator 瀏覽器尋找一種網(wǎng)頁(yè)腳本(此前的瀏覽器不具備互動(dòng)能力)。當(dāng)他們看到 Sun 公司的宣傳后,與 Sun 合作開發(fā)全新的腳本語(yǔ)言 javascript 。此前我一直不明白 js 既然不是 java 的腳本,為什么叫這個(gè)名字。現(xiàn)在懂了,因?yàn)楫?dāng)時(shí)新腳本語(yǔ)言的決策中, Sun 公司占了很大一環(huán)。
1995年5月 按照公司的要求(一個(gè)像 java 但是比 java 簡(jiǎn)單的腳本語(yǔ)言), Brendan Eich 僅用10天就寫出了 javascript 。
在我們膜拜大神的時(shí)候,也要認(rèn)清一個(gè)現(xiàn)實(shí),當(dāng)時(shí)給 Brendan Eich 的時(shí)間太短了,所以很多問題并沒有很好的解決,而且一邊模仿 java、c ,一邊還要簡(jiǎn)化數(shù)據(jù)類型、內(nèi)存模型。我覺得這就是為什么 js 的位運(yùn)算這么奇怪的原因。
js 完全套用了 java 的位運(yùn)算符。
但是 java 的位運(yùn)算是針對(duì)整數(shù)的,對(duì) js 沒什么用啊,因?yàn)? js 中,所有數(shù)字都保存為雙精度浮點(diǎn)型。如果使用它們的話, js 不得不將操作數(shù)先轉(zhuǎn)為整數(shù),然后再進(jìn)行運(yùn)算。
所以很多人不建議在 js 中使用位運(yùn)算,理由是 js 天生就會(huì)進(jìn)行類型轉(zhuǎn)換,使得效率降低。
golang原生數(shù)據(jù)類型
golang原生數(shù)據(jù)類型:按長(zhǎng)度:int8(-128-127)、int16、int32、int64。
布爾型:布爾型的值只可以是常量true或者false。一個(gè)簡(jiǎn)單的例子:varbbool=true。
數(shù)字類型:整型int和浮點(diǎn)型float32、float64,Go語(yǔ)言支持整型和浮點(diǎn)型數(shù)字,并且支持復(fù)數(shù),其中位的運(yùn)算采用補(bǔ)碼。
字符串類型:字符串就是一串固定長(zhǎng)度的字符連接起來(lái)的字符序列。Go的字符串是由單個(gè)字節(jié)連接起來(lái)的。Go語(yǔ)言的字符串的字節(jié)使用UTF-8編碼標(biāo)識(shí)Unicode文本。
派生類型:包括:(a)指針類型(Pointer)(b)數(shù)組類型?結(jié)構(gòu)化類型(struct)(d)Channel類型(e)函數(shù)類型(f)切片類型(g)接口類型(interface)(h)Map類型。
網(wǎng)頁(yè)題目:go語(yǔ)言反碼補(bǔ)碼 1反碼補(bǔ)碼
分享網(wǎng)址:http://ef60e0e.cn/article/doicgph.html