• 位数组


      在处理数字有许多位时,可以使用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 );
  • 相关阅读:
    How to access the properties of an object in Javascript
    他们不是机器人
    sql 使用整理
    地图上计算两点间的距离.(参考网络)
    window.location.reload被弃用?
    BitBlt
    BitBlt介绍
    C#大数计算 .Net Framework4.0以下
    C# ToString格式化
    Ubuntu修改时区和更新时间
  • 原文地址:https://www.cnblogs.com/pilgrim/p/9235935.html
Copyright © 2020-2023  润新知