C#位運算實際運用
前言
前幾天寫了一篇關於c#位操作,c#位運算基本概念與計算過程
最後提到一個實際問題
- 需求: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=longResult
- 我提出的疑問:能不能根據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
正確的做法根據longResult算出shortA、intA、shortB也是要用位運算的。
1.為什麼我要記錄下來
有很多最基本的知識點,沒有了解到,在遇到錯誤的時候,會走不少彎路,浪費很多不應該浪費的時間。說簡單點,基礎知識不牢固,工作效率低。
比如:一個二進位制數的第一位是從左邊開始算,還是從右邊開始算起?
我深信讀到這裡的人,至少有一部分人不知道。當然,我也是屬於這一部分人。(我並不想直接說出答案,可能會猜到有點人打開了百度)
為什麼要記錄下來?因為今天提交了一段垃圾程式碼關於整型合併的相互轉換。領導看了,很沉默,不說話,發了篇文章給我,讓我看,修改一下。其實我提交那段垃圾程式碼的時候心裡就很沒底懸得慌,感覺這樣做很不合適。學而時習之,溫故而知新。
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位的二進位制
8是int型別 32位的二進位制
20是short型別 16位的二進位制
從這個三個二進位制就可以得出long型別的64位二進位制,long值是4785074604605460
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位二進位制
向左移動48位後
step2:8的二進位制左移16位,(long)8<<16的結果是:524588
8的64位二進位制
向左移動16位後
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位二進位制
將這個long型別往右移動48位得到的64位二進位制,也就是16位有效值shortA,這個short就是17
longResult >>48完美得到shortA的值17,右位移也就是longResult整除2的48次方
shortA =(short)(longResult<<48)
step2:然後獲取中間32位intA的值,先將這個longResult右位移16位,得到後48位有效值
現在要取的後面32位有效值才是intA的值,再將(longResult>>16)&0xFFFFFFFF,做邏輯與運算,0xFFFFFFFF(4294967295)的64位二進位制全部都是1
與運算的規則1&1=1 、1&0=0、0&0=0,所以對後48位有效值做完邏輯與運算,就得到有效32位的intA
intA=(int)((longResult>>16)&0xFFFFFFFF)
intA的最終結果就是8
step3:最後獲取最右邊16位的shortB(將前面48位都變成0),只需要做一次與運算就可以,longResult做與運算的物件是0xFFFF(65535),有效16位全部都是1,二進位制如下
longResult&0xFFFF的最終結果就是20
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的二進位制位?
知道計算過程和位運算的基本概念,這些問題就非常簡單,會者不難,難者不會。