zoukankan      html  css  js  c++  java
  • 位数组

      在处理数字有许多位时,可以使用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 );
  • 相关阅读:
    Codeforces 1265A Beautiful String
    1039 Course List for Student (25)
    1038 Recover the Smallest Number (30)
    1037 Magic Coupon (25)
    1024 Palindromic Number (25)
    1051 Pop Sequence (25)
    1019 General Palindromic Number (20)
    1031 Hello World for U (20)
    1012 The Best Rank (25)
    1011 World Cup Betting (20)
  • 原文地址:https://www.cnblogs.com/pilgrim/p/9235935.html
Copyright © 2011-2022 走看看