zoukankan      html  css  js  c++  java
  • 实现一个BitArray类:索引器和位操作


    System.Collections命名空间下的BitArray相当于一个bool类型的数组bool[]。MSDN用BitArray做例子实现了一个索引器,今天研究了一下这个例子,对原来的实现做了一些改变,将>> 5操作变成了divide 32,敝人以为这样看起来会更直观。
    代码如下:

     

    public class MyBitArray
    {
        
    private int[] m_Bits;
        
    private int m_Length;
        
    static private const int MASK 0x1F;

        
    public MyBitArray(int length)
        {
            
    //Comment 1 
            m_Length = (length - 1/ 32 + 1;  
            m_Bits 
    = new int[m_Length];
        }

        
    public bool this[int index] 
        {
            
    //Comment 2
            get { return (m_Bits[index / 32& 1 << (index & MASK)) != 0; }
              
    set
            {
                
    if (value)
                    m_Bits[index 
    / 32|= 1 << (index & MASK);
                
    else
                    m_Bits[index 
    / 32&= ~(1 << (index & MASK));
            }
        }
    }

     

     


    Comment 1 :1个int占用4个字节,可以存储32个bit值。所以实际所需的int数组的长度是所传入length的1/32。length -1 是考虑到边界值32,(32-1)/32 + 1 =1,否则得到的结果是2,而此时只需1个int长度的内存即可。而对边界值0,(0-1)/32 + 1 = 1,也是没有问题的。

    Comment 2 :BitArray中的一系列bit值,可以看做被分段存储在了int元素中,index/32取出了index对应的bit值所在的int元素。再将1移动到合适的位上,进行与/或操作。看起来有点类似内存访问中段和页的概念。

    bit在数组内的存储如下:


    index的二进制表示其实可以看做被分成了两部分,6..n 这n-5位指示出所需的bit存放在哪个int块之后,1..5这5位恰好能表示0-31这32个数字,指示出bit存在该block的哪个位。
    以获取第index位的值为例
    第一步,index>>5得到bit所在的int块,也即上图的第k块
    第二步,0x1F也即0....011111,因此index&MASK正好得到后5位表示的数字,设为j,
    第三步,1 << (index&MASK) 生成一个mask: 0...1...0, 1正好处在第j位
    第四步,(m_Bits[index / 32] & 1 << (index&MASK))用上一步生成的mask 0...1...0与第k个int做&操作,从而得到第i位bit的值


    关于索引器:索引器与property最大的区别在于,property只有set方法带有参数,而indexer的get和set方法都带有默认参数index。另外property可以是static的,索引器当然不行。详细比较请看这里

    关于位操作:通常,当指定移动的位数溢出的时候,位移操作会自动对移动位数取模。这就是为什么上面的set方法中1 << index能将1移动到正确位置的原因。
    举例,8 >> 33; 相当于8 >> 1, 结果是4,而不是0。
    1 << 32; 相当于1 << 0, 结果还是1。

    有意思的是,变量类型为byte或short或int的时候,CLR取模的除数都是32,而不是随数据类型的长度变化。比如:
    short b = 1; b <<= 16; 
    得到的结果为0. 此时CLR并非对16取模。
    但如果数据被定义为long,则取模的除数会自动变成64。
    long l = 1; l <<= 32; 得到的值是4294967296,即2^32。







  • 相关阅读:
    利用WEBPART部件之间的数据连接功能,筛选知识库
    + 网页制作效果常用代码
    你或许还未听说过的一些ASP.NET 2.0要诀 [转]
    关闭Windows Server 2003关机事件跟踪程序
    Windows SharePoint Services 3.0 应用程序模板中文版(图解)
    零基础学Python不迷茫——基本学习路线及教程!
    小白安装Python环境详细步骤!
    Python入门第一课——Python的起源、发展与前景!
    7款公认比较出色的Python IDE,你值得拥有!
    Windows平台下gitbook的安装与使用
  • 原文地址:https://www.cnblogs.com/k330/p/1129670.html
Copyright © 2011-2022 走看看