本文介绍了是BitArray在C#中更快得到一个位值不是一个简单的一起选择按位转移?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

1)。 VAR bitValue =(的byteValue及(1 LT;<位编号))!= 0;



2) 。使用 System.Collections.BitArray 获取(位编号)方式




  • 什么是快?

  • 在什么情况下对.NET项目的 BitArray 可能比使用按位转移的简单结合更有用?


解决方案

BitArray 将是能够处理布尔值的任意数量的,而字节将仅持有8, INT 只有32等。这将是两者之间最大的区别。



此外, BitArray 工具的IEnumerable ,其中一个整体式显然不会。因此,一切都取决于你的项目的要求;如果你需要一个的IEnumerable 或数组一样的界面,然后用 BitArray

$ B $走b

我真的使用布尔[] 以上任何一种解决方案,只是因为它是更加明确的的什么的那种数据你保持跟踪。 ŧ



BitArray 位域将使用约1 / 8日的空间布尔[] ,因为它们打包8布尔值到一个单字节,而布尔本身会占用整个8位字节。使用位域的空间优势或 BitArray 不会,虽然事,直到你被存储的地段的bool 。 (数学留给了读者:-))






基准



结果:我的原始测试环境中,似乎 BitArray 的速度更快,但震级是作为自己与整型做同样的顺序。还测试了一个布尔[] ,这是勿庸置疑的最快的。访问单字节的内存将是比访问不同的字节各个位那么复杂。



与千万操作测试:
一个UInt32的位域了808毫秒。
一个BitArray(32)574了毫秒。
的List<布尔>(32)采取了436毫秒。



代码:

 类节目
{
静态无效的主要(字串[] args)
{
随机R =新的随机();
r.Next(1000);

const int的N =千万;

Console.WriteLine(测试与{0}操作,N);

Console.WriteLine(A UInt32的位域了{0}毫秒。TestBitField(R,N));
Console.WriteLine(A BitArray(32)采取了{0}毫秒。TestBitArray(R,N));
Console.WriteLine(A名单<布尔>(32)采取了{0}毫秒。TestBoolArray(R,N));

Console.Read();
}


静态长TestBitField(随机R,INT N)
{
UInt32的位域= 0;

变种SW = Stopwatch.StartNew();
的for(int i = 0; I< N;我++){$​​ B
$ B SetBit(REF位域,r.Next(32),TRUE);
布尔B = GETBIT(位字段,r.Next(32));
SetBit(REF位域,r.Next(32),B);
}
sw.Stop();
返回sw.ElapsedMilliseconds;
}

静态布尔GETBIT(UInt32的X,INT BITNUM){
如果(BITNUM℃,|| BITNUM> 31)
抛出新ArgumentOutOfRangeException(无效比特数);

则返回(x及(1下;&下; BITNUM))!= 0;
}

静态无效SetBit(参考UInt32的X,INT BITNUM,布尔VAL)
{
如果(BITNUM℃,|| BITNUM> 31)
抛出新ArgumentOutOfRangeException(无效的位号);

如果(VAL)
X | =(UInt32的)(1 <,否则
X - 放大器; =〜(UInt32的)(1 <}



静态长TestBitArray(随机R,INT N)
{
BitArray B =新BitArray(32,FALSE) ; // 40字节

变种SW = Stopwatch.StartNew();
的for(int i = 0; I< N;我++){$​​ B
$ B b.Set(r.Next(32),TRUE);
布尔V = b.Get(r.Next(32));
b.Set(r.Next(32),ⅴ);
}
sw.Stop();
返回sw.ElapsedMilliseconds;
}



静态长TestBoolArray(随机R,INT N)
{
布尔[] BA =新布尔[32] ;

变种SW = Stopwatch.StartNew();
的for(int i = 0; I< N;我++){$​​ B
$ B BA [r.Next(32)] =真;
布尔V = BA [r.Next(32)];
BA [r.Next(32)] = v的
}
sw.Stop();
返回sw.ElapsedMilliseconds;
}
}


1). var bitValue = (byteValue & (1 << bitNumber)) != 0;

2). using System.Collections.BitArray with a Get( bitNumber ) method

  • What is faster?
  • In what situations for the .NET projects BitArray could be more useful than a simple conjunction with the bitwise shift?

解决方案

BitArray is going to be able to handle an arbitrary number of boolean values, whereas a byte will hold only 8, int only 32, etc. This is going to be the biggest difference between the two.

Also, BitArray implements IEnumerable, where a integral type obviously does not. So it all depends on the requirements of your project; if you need an IEnumerable or array-like interface, then go with the BitArray.

I would actually use a bool[] over either solution, simply because it is more explicit in what kind of data you're keeping track of. T

BitArray or bitfield will use approximately 1/8th the space of a bool[] because they "pack" 8 boolean values into a single byte, whereas a bool by itself will take up the whole 8-bit byte. The space advantage of using a bitfield or BitArray isn't going to matter though until you being storing lots of bools. (The math is left up to the reader :-))


Benchmark

Results: For my primitive test environment, it appears that BitArray is a bit faster, but is on the same order of magnitude as doing it yourself with an integral type. Also tested was a bool[], which was unsurprisingly the fastest. Accessing single bytes in memory is going to be less complex than accessing individual bits in different bytes.

Testing with 10000000 operations:
   A UInt32 bitfield took 808 ms.
   A BitArray (32) took 574 ms.
   A List<bool>(32) took 436 ms.

Code:

class Program
{
    static void Main(string[] args)
    {
        Random r = new Random();
        r.Next(1000);

        const int N = 10000000;

        Console.WriteLine("Testing with {0} operations:", N);

        Console.WriteLine("   A UInt32 bitfield took {0} ms.", TestBitField(r, N));
        Console.WriteLine("   A BitArray (32) took {0} ms.", TestBitArray(r, N));
        Console.WriteLine("   A List<bool>(32) took {0} ms.", TestBoolArray(r, N));

        Console.Read();
    }


    static long TestBitField(Random r, int n)
    {
        UInt32 bitfield = 0;

        var sw = Stopwatch.StartNew();
        for (int i = 0; i < n; i++) {

            SetBit(ref bitfield, r.Next(32), true);
            bool b = GetBit(bitfield, r.Next(32));
            SetBit(ref bitfield, r.Next(32), b);
        }
        sw.Stop();
        return sw.ElapsedMilliseconds;
    }

    static bool GetBit(UInt32 x, int bitnum) {
        if (bitnum < 0 || bitnum > 31)
            throw new ArgumentOutOfRangeException("Invalid bit number");

        return (x & (1 << bitnum)) != 0;
    }

    static void SetBit(ref UInt32 x, int bitnum, bool val)
    {
        if (bitnum < 0 || bitnum > 31)
            throw new ArgumentOutOfRangeException("Invalid bit number");

        if (val)
            x |= (UInt32)(1 << bitnum);
        else
            x &= ~(UInt32)(1 << bitnum);
    }



    static long TestBitArray(Random r, int n)
    {
        BitArray b = new BitArray(32, false);     // 40 bytes

        var sw = Stopwatch.StartNew();
        for (int i = 0; i < n; i++) {

            b.Set(r.Next(32), true);
            bool v = b.Get(r.Next(32));
            b.Set(r.Next(32), v);
        }
        sw.Stop();
        return sw.ElapsedMilliseconds;
    }



    static long TestBoolArray(Random r, int n)
    {
        bool[] ba = new bool[32];

        var sw = Stopwatch.StartNew();
        for (int i = 0; i < n; i++) {

            ba[r.Next(32)] = true;
            bool v = ba[r.Next(32)];
            ba[r.Next(32)] = v;
        }
        sw.Stop();
        return sw.ElapsedMilliseconds;
    }
}

这篇关于是BitArray在C#中更快得到一个位值不是一个简单的一起选择按位转移?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-21 01:54