位數組


  在處理數字有許多位時,可以使用C#中的BitArray類和BitVector32結構。BitArray類與BitVector32結構的區別是:BitArray類可以重新設置大小,對於事先不知道需要的位數,可以使用BitArray類,它可以包含很多位。BitVector32結構是基於棧的,相對於類比較快,但是它只含有32位,存儲在一個整數中。

1、BitArray類

  BitArray類是一個引用類型,它包含一個int數組,每32位使用一個新整數。每一個位都是一個bool值。

  創建一個位數組:

//*****************創建位數組***********************
BitArray bits = new BitArray(8);//創建一個包含8位的數組 bits.SetAll(true);//將8個位都設置為true bits.Set(1, false);//將下標為1(第二個位)設置為false bits[5] = false;//將下標為5的位設置為false Console.WriteLine("Initialized: "); foreach (bool b in bits) { Console.WriteLine(b ? 1 : 0); }

   如果創建一個位數組時,在構造函數中傳入一個位數組,那么新創建的位數組將和參數位數組具有相同的值。在構造位數組時,可以使用字節數組、int類型數組、bool數組和位數組進行初始化構造位數組。注意:只能是數組形式。如果傳入一個int類型的數字,則認為創建int長度的位的位數組。

  位數組中有許多方法,如:Set()設置某個位上的值;SetAll()設置所有位上的值;Not()對所有位取反;And()、Or()、Xor()用於兩個位數組之間的合並運算等方法。

2、BitVector32結構

  如果事先知道需要的位數,可以使用BitVector32結構代替BitArray類。因為BitVector32是值類型的關系,所以在效率上相對較高。對於需要更多的位可以使用多個BitVector32結構或者BitArray類。

  使用默認構造函數創建一個BitVector32結構,所有位都默認為false。然后創建掩碼,以訪問位矢量中的位。使用索引器訪問對應的位,並設置相應的字段。

BitVector32 bits1 = new BitVector32();
int bit1 = BitVector32.CreateMask();      //創建掩碼,運行后bit1=1;
int bit2 = BitVector32.CreateMask(bit1);//創建掩碼,運行后bit2=2;
int bit3 = BitVector32.CreateMask(bit2);//創建掩碼,運行后bit3=3;
int bit4 = BitVector32.CreateMask(bit3);//創建掩碼,運行后bit4=4;
int bit5 = BitVector32.CreateMask(bit4);//創建掩碼,運行后bit5=5;
bits1[bit1] = true;
bits1[bit2] = true;
bits1[bit3] = false;
bits1[bit4] = true;
bits1[bit5] = true;
Console.WriteLine(bits1);//輸出為:BitVector32{00000000000000000000000000011011}

  也可以自己創建掩碼,一次性設置多個位。例如十六進制的abcdef與二進制的1010 1011 1100 1101 1110 1111相同。因此對於一個新創建的bits:

  bits[0xabcdef] = true;//輸出為:BitVector32{00000000101010111100110111101111}

  IPv4中的應用:IPv4地址定義為一個4字節的數,該數存儲在一個整數中。可以定義4個片段,把這個整數拆分開。在多播IP消息中,使用了幾個32位的值。其中一個32位的值放在這些片段中:16位表示源號,8位表示查詢器的查詢內部碼,3位表示查詢器的健壯變量,1位表示抑制標志,保留4位。也可以自己定義位含義,以節省內存。下面的例子中,模擬接收到值0x79abcdef:

int received = 0x79abcdef;
BitVector32 bits = new BitVector32(received);//bits結構為:BitVector32{01111001101010111100110111101111}

  接着創建6個片段:第一個片段A需要12位,由十六進制值0xffff定義;第二個片段B需要8位;第三個片段C需要4位;第四個片段D和第五個片段E需要3位;第六個片段需要2位。除第一個片段外,其余片段皆將上一個片段作為參數傳遞,使得該片段從上一片段的結尾處開始。CreateSection()方法返回一個BitVector32.Section類型的值,該類型包含了該片段的偏移量和掩碼:

//sections: FF EEE DDD CCCC BBBBBBBB AAAAAAAAAAAA
BitVector32.Section sectionA = BitVector32.CreateSection(0xfff);
BitVector32.Section sectionB= BitVector32.CreateSection(0xff, sectionA);
BitVector32.Section sectionC = BitVector32.CreateSection(0xf, sectionB);
BitVector32.Section sectionD = BitVector32.CreateSection(0x7, sectionC);
BitVector32.Section sectionE = BitVector32.CreateSection(0x7, sectionD);
BitVector32.Section sectionF = BitVector32.CreateSection(0x3, sectionE);

  把一個BitVector32.Section類型的值傳遞給BitVector32結構的索引器,會返回一個int,它映射到位矢量的片段上。

  首先創建一個展示方法IntToBInaryString():

static string IntToBinaryString(int bits,bool removeTrailingZero)
{
    StringBuilder builder = new StringBuilder(32);

    for(int i=0;i<32;i++)
    {
        if ((bits & 0x80000000) != 0)
        {
            builder.Append("1");
        }
        else
        {
            builder.Append("0");
        }
        bits=bits << 1;
    }
    string s = builder.ToString();
    if(removeTrailingZero)
    {
       return s.TrimStart('0');
    }
    return s;
}

  結果顯示了片段A~F的位表示:

Console.WriteLine("Section A: {0}", IntToBinaryString(bits[sectionA], true));//輸出為:Section A: 110111101111
Console.WriteLine("Section B: {0}", IntToBinaryString(bits[sectionB], true));//輸出為: Section B: 10111100
Console.WriteLine("Section C: {0}", IntToBinaryString(bits[sectionC], true));//輸出為:Section C: 1010
Console.WriteLine("Section D: {0}", IntToBinaryString(bits[sectionD], true));//輸出為:Section D: 1
Console.WriteLine("Section E: {0}", IntToBinaryString(bits[sectionE], true));//輸出為:Section E: 111
Console.WriteLine("Section F: {0}", IntToBinaryString(bits[sectionF], true));//輸出為:Section F: 1

  以上顯示結果,與最開始的整數位一一對應:

//BitVector32{ 01 111 001 1010 10111100 110111101111}
//sections:    FF EEE DDD CCCC BBBBBBBB AAAAAAAAAAAA

3、BitArray與Byte之間的轉換

/// <summary>        
/// 通過位構建字節        
/// </summary>      
/// <param name="boolArray">bool位值</param>       
/// <returns>字節數組</returns>       
byte[] ConvertToByte(bool[] boolArray)
{
    int num = (int)Math.Ceiling((boolArray.Length / 8.0));    //向上取整          
    bool[] newBool = new bool[num * 8];
    boolArray.CopyTo(newBool, 0);              //補位   
    BitArray bits = new BitArray(newBool);
    byte[] bytes = new byte[num];
    bits.CopyTo(bytes, 0);
    return bytes;
}

bool[] bits = new bool[] { true, false, false, false, false, false, true, true, };
//將其轉換為位值            
byte[] myByte = ConvertToByte(bits);

//獲取每個位上的值:false/true            
BitArray recoveredBit = new BitArray( myByte );

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM