C#位運算實際運用

前言

前幾天寫了一篇關於c#位操做,c#位運算基本概念與計算過程
最後提到一個實際問題html

  • 需求:C# 用兩個short,一個int32拼成一個long型
  • 要求:如今有兩個short和一個int,須要拼成一個long型,高16位用short,中間32位用int,最低16位用另一個short
    https://bbs.csdn.net/topics/392202825?page=1
  • 答案:((long)shortA << 48 )+ ((long)intA << 16)+ shortB=longResultc#

  • 我提出的疑問:能不能根據longResult反推出shortA、intA、shortB
  • 我當時的回答:是一個極其錯誤的答案,原文片斷以下
    那麼疑問來了能夠經過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

1.爲何我要記錄下來

有不少最基本的知識點,沒有了解到,在遇到錯誤的時候,會走很多彎路,浪費不少不該該浪費的時間。說簡單點,基礎知識不牢固,工做效率低。
好比:一個二進制數的第一位是從左邊開始算,仍是從右邊開始算起?
我深信讀到這裏的人,至少有一部分人不知道。固然,我也是屬於這一部分人。(我並不想直接說出答案,可能會猜到有點人打開了百度)
爲何要記錄下來?由於今天提交了一段垃圾代碼關於整型合併的相互轉換。領導看了,很沉默,不說話,發了篇文章給我,讓我看,修改一下。其實我提交那段垃圾代碼的時候內心就很沒底懸得慌,感受這樣作很不合適。學而時習之,溫故而知新。code

2.兩個short一個int如何合併一個long?

需求:
高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

3.根據long如何反推出合併前的兩個short和一個int

完美三部曲,幹就完事了。
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;

4.總結

高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,謝謝!

相關文章
相關標籤/搜索