位数组

Posted pilgrim

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了位数组相关的知识,希望对你有一定的参考价值。

  在处理数字有许多位时,可以使用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

 








以上是关于位数组的主要内容,如果未能解决你的问题,请参考以下文章

华为OD机试 - 众数和中位数(Python)| 真题+思路+代码

计算特定组的百分位数

计算特定组的百分位数

R按四分位数表示的多个组的平均值[重复]

是时候进入位数组数组了

Icarus Verilog:多位数组解析错误