前幾天寫了一篇關於c#位操做,c#位運算基本概念與計算過程
最後提到一個實際問題html
答案:((long)shortA << 48 )+ ((long)intA << 16)+ shortB=longResultc#
我當時的回答:是一個極其錯誤的答案,原文片斷以下
那麼疑問來了能夠經過longResult返推出shortA,shortB,intA。固然是不能這是直接相加。
返回不該該用這種組合字符串的方式
((long)shortA << 48 ) 16位二進制0或1的字符串
((long)intA << 16) 32位二進制0或1的字符串
shortB 16位二進制0或1的字符串
將這三個字符串拼接成64位二進制字符串,再將這個64位二進制字符串轉成一個long
固然這種方式獲得的結果是沒毛病的,分割二進制的位數,對應去設置0或1。可是作法太草率,沒有動腦筋,這種作法效率過低。
正確的作法根據longResult算出shortA、intA、shortB也是要用位運算的。.net
有不少最基本的知識點,沒有了解到,在遇到錯誤的時候,會走很多彎路,浪費不少不該該浪費的時間。說簡單點,基礎知識不牢固,工做效率低。
好比:一個二進制數的第一位是從左邊開始算,仍是從右邊開始算起?
我深信讀到這裏的人,至少有一部分人不知道。固然,我也是屬於這一部分人。(我並不想直接說出答案,可能會猜到有點人打開了百度)
爲何要記錄下來?由於今天提交了一段垃圾代碼關於整型合併的相互轉換。領導看了,很沉默,不說話,發了篇文章給我,讓我看,修改一下。其實我提交那段垃圾代碼的時候內心就很沒底懸得慌,感受這樣作很不合適。學而時習之,溫故而知新。code
需求:
高16位用short,中間32位用int,最低16位用另一個short。
答案:((long)shortA << 48 )+ ((long)intA << 16)+ shortB
具體的計算過程是這樣的
距離shortA 是 17,intA是8,shortB是20
17是short類型 16位的二進制htm
0000 0000 0001 0001
8是int類型 32位的二進制對象
0000 0000 0000 0000 0000 0000 0000 1000
20是short類型 16位的二進制blog
0000 0000 0001 0100
從這個三個二進制就能夠得出long類型的64位二進制,long值是4785074604605460字符串
0000 0000 0001 0001 0000 0000 0000 0000 0000 0000 0000 1000 0000 0000 0001 0100
step1:將shortA 17的二進制左位移48位也就是這個long類型最左邊16位(17必定要先轉成long再左位移,必定要記住這一點)
(long)17<<48 的結果是4785074604081152 17乘以2的48次方法
2的49次方(第一個1在49位)加上2的53次方(第二個1在53位)
17的64位二進制get
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 0001
向左移動48位後class
0000 0000 0001 0001 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
step2:8的二進制左移16位,(long)8<<16的結果是:524588
8的64位二進制
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1000
向左移動16位後
0000 0000 0000 0000 0000 0000 0000 1000 0000 0000 0000 0000 0000 0000 0000 0000
step3 :
(long)17<<48 +(long)8<<16 =4785074604081152 +524588
有效位數已經佔滿了前48位,剩下的有效16位就是20
最終的結果就是
((long)8<<16)+((long)17<<48)+20 =4785074604605460
完美三部曲,幹就完事了。
step1:首先要獲取前16位有效值shortA
咱們已經知道了longResult 4785074604605460的64位二進制
0000 0000 0001 0001 0000 0000 0000 0000 0000 0000 0000 1000 0000 0000 0001 0100
將這個long類型往右移動48位獲得的64位二進制,也就是16位有效值shortA,這個short就是17
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 0001
longResult >>48完美獲得shortA的值17,右位移也就是longResult整除2的48次方
shortA =(short)(longResult<<48)
step2:而後獲取中間32位intA的值,先將這個longResult右位移16位,獲得後48位有效值
0000 0000 0000 0000 0000 0000 0001 0001 0000 0000 0000 0000 0000 0000 0000 1000
如今要取的後面32位有效值纔是intA的值,再將(longResult>>16)&0xFFFFFFFF,作邏輯與運算,0xFFFFFFFF(4294967295,這是一個UInt32類型,有效位的32位所有是1)的64位二進制
0000 0000 0000 0000 0000 0000 0000 0000 1111 1111 1111 1111 1111 1111 1111 1111
與運算的規則1&1=1 、1&0=0、0&0=0,因此對後48位有效值作完邏輯與運算,就獲得有效32位的intA
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1000
intA=(int)((longResult>>16)&0xFFFFFFFF)
intA的最終結果就是8
step3:最後獲取最右邊16位的shortB(將前面48位都變成0),只須要作一次與運算就能夠,longResult作與運算的對象是0xFFFF(65535),有效16位所有都是1,二進制以下
0000 0000 0000 0000 0000 0000 0000 0000 1111 1111 1111 1111 1111 1111 1111 1111
longResult&0xFFFF的最終結果就是20
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 0100
shortB=(short)(longResult&0xFFFF)=20;
高16位用short,中間32位用int,最低16位用另一個short。
longResult=((long)shortA << 48 )+ ((long)intA << 16)+ shortB
根據longResult獲取前16位shortA,中間32位intA,後16位shortB
shortA=(short)(longResult>>48) intA=(int)((longResult>>16)&0xFFFFFFFF) shortB=(short)(longResult&0xFFFF)
那麼
想用一個byte存兩個數,如何相互轉換?
如何獲取和設置一個int的二進制位?
知道計算過程和位運算的基本概念,這些問題就很是簡單,會者不難,難者不會。
有興趣關注一下個人我的公衆號,支持一下xamarin,謝謝!