前幾天寫了兩篇關於c#位運算的文章
c#位運算基本概念與計算過程
C#位運算實際運用
在文中也提到了位運算的實際做用之一就是合併整型,當時引用了一個問題:
C# 用兩個short,一個int32拼成一個long型,高16位用short,中間32位用int,最低16位用另一個short。
答案以下:
高16位shortA、中間32位intA、低16位shortBhtml
longResult=((long)shortA << 48 )+ ((long)intA << 16)+ shortB
根據longResult獲取前16位shortA,中間32位intA,後16位shortBc#
shortA=(short)(longResult>>48) intA=(int)((longResult>>16)&0xFFFFFFFF) shortB=(short)(longResult&0xFFFF)
評論者pushouli、czd890 評論到,合併這個long類型的結果是使用加法計算,可使用位邏輯或運算,想了想確實使用| 位邏輯或運算也是能夠解決問題的,可以實現相互轉換。性能
1樓 2019-04-30 07:28 pushouli 簡單明瞭,但感受合併那裏,不該該用加法去算,用|運算符更合適。
11樓 2019-04-30 18:10 czd890
@ pushouli 用+ 和 | 在這裏性能上應該沒有太大區別。 可是感受用 | 更能表達意思一些測試
longResult=(((long)shortA << 48) |((long)intA << 16)) | (long)shortB
1|0=一、1|1=一、0|0=0code
其計算結果longResult是同樣的,運算方式不同,其計算過程能夠看看前面寫的一篇
C#位運算實際運用
如圖:
這篇文章就將記錄兩個知識點:
1.負數的二進制位表示法
2.位運算如何直接操做Int類型某一位htm
原碼:一個整數按照絕對值的大小轉換成的二進制數,稱爲原碼
一個short 16位的整數9的原碼是:blog
0000 0000 0000 1001
反碼:一個二進制數按位取反,所得的二進制數成爲原二進制數的反碼
取9的二進制數的反碼,可使用位邏輯非運算 ~
取反後的16位二進制圖片
1111 1111 1111 0110
補碼:反碼加1稱爲補碼,簡而言之,要獲得一個屬的補碼,先獲得這個數的反碼,而後再將反碼加上1,所得數稱爲補碼
那麼9的補碼也就是ci
1111 1111 1111 0110
加上1的結果,以下:開發
1111 1111 1111 0111
即-9的16位二進制表示是
1111 1111 1111 0111
如圖:
話很少說,直接明確三點結論:
1.實際開發中,都用的是有符號的Int(應該默認強制要求),只有整型有有無符號的特徵,Double、Decimal,是沒有這種特徵的。
2.無符號數中,全部的位都用於直接表示該值的大小。
3.有符號數中,最高位用於表示正負。
這裏仍是簡單地囉嗦幾句關於有符號和無符號的區別,UInt32和Int32的區別
這裏說的Int指的是32位有符號的類型
Int32的值範圍是 -2147483648 至2147483647,也就是
-2的31次方到2的31次方-1
符號位表示的意義就在於此,最前面的位表示正負。
-2148483648的32位二進制是:
1000 0000 0000 0000 0000 0000 0000 0000
2147483647的32位二進制是:
0111 1111 1111 1111 1111 1111 1111 1111
那麼c#中UInt32的最大值是什麼呢?
UInt32的範圍是0到2的32次方4294967295,最大值32位二進制是
1111 1111 1111 1111 1111 1111 1111 1111
因此得出結論無符號只能表示正數,有符號能夠表示正負數。
如圖:
前面已經說到,Int表示的是有符號的,最高位表示的正負,一個Int有32位,雖然咱們能夠直接操做這32位,可是若是直接操做明顯會改變數據類型的正負、最大範圍。
這裏寫了一個泛型的示例,操做整型(int、short、long)的每一位。
/// <summary> /// Int16\Int32\Int64類型 /// </summary> /// <returns>true 1\false 0的集合</returns> public static IEnumerable<bool> GetIntOfBitList<T>(T intVal) { Type intType = intVal.GetType(); byte bitlength = 0; if (intType == typeof(Int32)) bitlength = 32; else if (intType == typeof(Int16)) bitlength = 16; else if (intType == typeof(Int64)) bitlength = 64; else throw new ArgumentException("必須是整型"); object intOject = (object)intVal; var resultList = new List<bool>(bitlength); for (var i = 0; i < bitlength; i++) { var temoIntBit = 1 << i; if (intType == typeof(Int32)) resultList.Add((((Int32)intOject) & temoIntBit) == temoIntBit); if (intType == typeof(Int16)) resultList.Add((((Int16)intOject) & temoIntBit) == temoIntBit); if (intType == typeof(Int64)) resultList.Add((((Int64)intOject) & temoIntBit) == temoIntBit); } return resultList; } /// <summary> /// 獲取T整型中某一位的值 /// </summary> /// <typeparam name="T">泛型類型包括int\short\long</typeparam> /// <param name="intVal">int\short\long</param> /// <param name="index">從右到左0-T的總位數</param> /// <returns>true:1\false:0</returns> public static bool GetBitValue<T>(T intVal,byte index) { Type intType = intVal.GetType(); byte bitlength = 0; if (intType == typeof(Int32)) bitlength = 32; else if (intType == typeof(Int16)) bitlength = 16; else if (intType == typeof(Int64)) bitlength = 64; else throw new ArgumentException("必須是整型"); if (index > bitlength-1 || index < 1) throw new ArgumentOutOfRangeException("index"); object intOject = (object)intVal; var tempBit = 1 << index; if (intType == typeof(Int32)) return (((int)intOject) & tempBit) == tempBit; else if (intType == typeof(Int16)) return (((Int16)intOject) & tempBit) == tempBit; else return (((Int64)intOject) & tempBit) == tempBit; } /// <summary> /// 設置整型數據中某一位的值 /// </summary> /// <typeparam name="T">int\short\long</typeparam> /// <param name="intVal">設置前的值</param> /// <param name="index">從右到左0-T的總位數</param> /// <param name="bitValue">須要設置的值 true:1\false:0</param> /// <returns>設置位值後新的整型</returns> public static T SetBitValue<T>(T intVal,byte index,bool bitValue) { Type intType = intVal.GetType(); byte bitlength = 0; if (intType == typeof(Int32)) bitlength = 32; else if (intType == typeof(Int16)) bitlength = 16; else if (intType == typeof(Int64)) bitlength = 64; else throw new ArgumentException("必須是整型"); //不能去設置最高位 if (index >= bitlength-1 || index < 1) throw new ArgumentOutOfRangeException("index"); object intOject = (object)intVal; var tempBit = 1 << index; if (intType == typeof(Int32)) { int tempInt = (int)intOject; return (T)((bitValue ? (tempInt | tempBit) : (tempInt & ~tempBit)) as Object); } else if (intType == typeof(Int16)) { Int16 tempInt = (Int16)intOject; return (T)((bitValue ? (tempInt | tempBit) : (tempInt & ~tempBit)) as Object); } else { Int64 tempInt = (Int64)intOject; return (T)((bitValue ? (tempInt | tempBit) : (tempInt & ~tempBit)) as Object); } }
測試截圖:
思考:這個方法能操做負數嗎?