位操作:BitVector32结构 z
目錄
- 溫習位操作
- BitVector32的位操作
- CreateMask方法
- 使用BitVector32.Section來存儲小整數
BitVector32結構體位于System.Collections.Specialized命名空間內,相對.NET中另外一個位容器BitArray,他的優點是速度快,占用空間小,并可以存儲小數字。他內部用一個32位的整數來存儲數據,因此只能存儲32位的比特數據。
?
?
返回目錄
溫習位操作
在看BitVector32前,溫習一下簡單的位操作還是很有必要的,常見的位操作無非就是與(AND),或(OR),非(NOT)。一般情況下,將一位設置成1就是把這個為或1的操作,將一位設置成0就是把這個位與0的操作。同時或0,與1結果不變。
這樣的話,比如一個8位的數據:
0000 1111我們想把第二個0設置成1,那么把他和下面這個數進行或操作:
0100 0000結果就是
0100 1111第二位變成了1
還是這個數
0000 1111如果想把最后一個1設置成0,那么把他和下面這個數進行與操作
1111 1110結果就是
0000 1110?
那么我們可以這樣總結一下:
想要操作一個位,我們把其他位設置成0,把這個位設置成1,這個數就是所謂的位掩碼(也稱位屏蔽,MSDN里用的是位屏蔽)。
那么如果想打開一個位(就是把這個位設置成1):源數據 = 源數據 OR 位掩碼。
如果想關掉一個位(就是把這個位設置成0):源數據 = 源數據 AND 位掩碼取反。
(位掩碼取反就是非(NOT)操作:0變成1,1變成0)。
?
?
返回目錄
BitVector32的位操作
了解了基本位操作BitVector32的理解就會簡單多了。
首先BitVector32本質上用一個32位的數來表示數據,那么初始化BitVector32結構時必須制定一個最初值,用戶可以傳入一個int或者另一個已經存在的BitVector32來構造一個新的BitVector32.
BitVector32的Data屬性返回一個int用來表示內部數據,如果用來顯示BitVector32的內容,這個Data是沒有意義的,因為他是十進制化的結果,這時候用BitVector32的ToString方法就可以返回有用的文字說明。
BitVector32 bits =newBitVector32(0xF); //初始化BitVector32:設置低4位為1 0x 00 00 00 00 00 00 00 0F Console.WriteLine(bits.Data); //(十六進制)0xF 等于 (二進制)1111 等于 (十進制)15 所以輸出15 Console.WriteLine(bits.ToString()); //輸出:BitVector32{00000000000000000000000000001111} (看得出來:后四位是1)?
接下來就是最重要的位操作了。
BitVector32結構體提供索引器(Indexer)可以直接通過bool對象操作BitVector32結構,索引器參數是int,這個int可不是指第幾位的意思(BitArray中的索引器是第幾位),而是需要一個位掩碼(位屏蔽),通過這個BitVector32通過這個位掩碼來操作內部比特位,來看看Reflector下BitVector32索引器的源碼
structBitVector32 { //data 就是 BitVector32的Data屬性的對應字段 publicboolthis[int bit] { get { return ((this.data & bit) == ((ulong)bit)); //通過數據和掩碼的與操作,來將其他位清0,保留掩碼的設置位 //如果操作后的結果等于掩碼,很顯然這是操作位就是1,返回true //否則的話,返回false } set { if (value) { this.data |= (uint)bit; //數據 = 數據 OR 掩碼,將指定位設置成1 } else { this.data &= (uint)~bit; //數據 = 數據 AND 掩碼取反,將指定位設置成0 //C# 取反位操作運算符:~ } } }}
上面代碼我加了注釋,可以看到,BitVector32的位操作就是利用普通位掩碼的操作。
?
好了那么用BitVector32索引器操作其實就是定義好位掩碼,接著取回信息或者賦值就可以了。
//注意using System.Collections.Specialized;int mask1 =1; //掩碼代表最后一位:二進制表示:0...0001 int mask2 =4; //掩碼代表倒數第三位:二進制表示:0...0000100
BitVector32 bits =newBitVector32(-1); //-1補碼:1...1111 //設置BitVector32全部為1 Console.WriteLine(bits);
Console.WriteLine("設置最后一位和倒數第三位位0"); bits[mask1] = bits[mask2] =false; Console.WriteLine(bits);
Console.WriteLine("設置倒數第三位為1"); bits[mask2] =true; Console.WriteLine(bits);
?
輸出:
BitVector32{11111111111111111111111111111111} 設置最后一位和倒數第三位位0 BitVector32{11111111111111111111111111111010} 設置倒數第三位為1 BitVector32{11111111111111111111111111111110}?
?
返回目錄
CreateMask方法
BitVector還有一個CreateMask方法,他的作用就是方便用戶定義位掩碼。
?
CreateMask(無參數):返回第一個位(最低位)的位掩碼,那么就是0…00001,十進制的話就是1
CreareMask(int):首先判斷一直位掩碼的合法性,并返回向左移1位的結果。
參考CreateMask的源代碼:
publicstaticint CreateMask(int previous) { if (previous ==0) { return1; } if (previous ==-2147483648) //這個數等于Int32.MinValue 二進制是100...0,無法再向左移位,因此異常 { thrownewInvalidOperationException(SR.GetString("BitVectorFull")); //拋出異常 } return (previous <<1); //向左移1位 }?
當然如果你掌握了上述位操作和位掩碼的概念,我個人感覺CreateMask有點多此一舉,我們就直接用MSDN的例子(我改了改注釋)
// 初始化BitVector32:全部0 BitVector32 myBV =newBitVector32(0);// 創建最低位的掩碼,然后陸續創建倒數第二位,倒數第三位……倒數第五位的掩碼 int myBit1 =BitVector32.CreateMask(); int myBit2 =BitVector32.CreateMask(myBit1); int myBit3 =BitVector32.CreateMask(myBit2); int myBit4 =BitVector32.CreateMask(myBit3); int myBit5 =BitVector32.CreateMask(myBit4); Console.WriteLine("最初值: \t{0}", myBV.ToString());
// 設置倒數第三位為1 myBV[myBit3] =true; Console.WriteLine("myBit3 = TRUE \t{0}", myBV.ToString());
// 將掩碼加起來,同時設置兩個位 myBV[myBit4 + myBit5] =true; Console.WriteLine("myBit4 + myBit5 = TRUE \t{0}", myBV.ToString()); myBV[myBit1 | myBit2] =true; Console.WriteLine("myBit1 | myBit2 = TRUE \t{0}", myBV.ToString());
?
輸出:
最初值: BitVector32{00000000000000000000000000000000} myBit3 = TRUE BitVector32{00000000000000000000000000000100} myBit4 + myBit5 = TRUE BitVector32{00000000000000000000000000011100} myBit1 | myBit2 = TRUE BitVector32{00000000000000000000000000011111}如果你手動輸出上面例子中的myBit1-5的值,其實就是我們上面講到的倒數一到五位的掩碼值。
總結
以上是生活随笔為你收集整理的位操作:BitVector32结构 z的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Oracle日期相关
- 下一篇: 初学java之菜单条,菜单,菜单项的设置