最有效的方法来颠倒BitArray的顺序?

时间:2011-01-25 08:14:13

标签: c# bitarray

我一直想知道在C#中反转BitArray顺序的最有效方法是什么。为了清楚起见,我不想通过调用.Not()来反转Bitarray。我想要反转数组中位的顺序。

干杯, 克里斯

6 个答案:

答案 0 :(得分:27)

public void Reverse(BitArray array)
{
    int length = array.Length;
    int mid = (length / 2);

    for (int i = 0; i < mid; i++)
    {
        bool bit = array[i];
        array[i] = array[length - i - 1];
        array[length - i - 1] = bit;
    }    
}

答案 1 :(得分:7)

对于长数组和相对较少的用途,只需将其包装:

    class BitArrayReverse
    {
        private BitArray _ba;

        public BitArrayReverse(BitArray ba) { _ba = ba; }

        public bool this[int index]
        {
            get { return _ba[_ba.Length - 1 - index]; }
            set { _ba[_ba.Length - 1 - index] = value; }
        }

    }

答案 2 :(得分:4)

这将是最好的方式 反转MSB&lt; - &gt;在for循环中使用XOR的任何长度的LSB

public static BitArray BitsReverse(BitArray bits)
{
    int len = bits.Count;
    BitArray a = new BitArray(bits);
    BitArray b = new BitArray(bits);

    for (int i = 0, j = len-1; i < len; ++i, --j)
    {
         a[i] = a[i] ^ b[j];
         b[j] = a[i] ^ b[j];
         a[i] = a[i] ^ b[j];
    }

    return a; 
} 
// in   010000011010000011100b
// out  001110000010110000010b

答案 3 :(得分:2)

 Dim myBA As New BitArray(4)
 myBA(0) = True
 myBA(1) = False
 myBA(2) = True
 myBA(3) = True
 Dim myBoolArray1(3) As Boolean
 myBA.CopyTo(myBoolArray1, 0)
 Array.Reverse(myBoolArray1)
 myBA = New BitArray(myBoolArray1)

答案 4 :(得分:0)

因为大小如果固定在8位只是从下面的“表格”查找就足够了 - 在处理普通byte时,查找可能是最快捷的方式。然而,用于获取/设置数据的BitSet的额外开销可能使查找益处无效。此外,需要考虑初始构建成本和持久开销(但值可以编码为数组文字... ick!)

另一方面,如果数据 8位(永远),并且“性能很重要”,为什么要使用BitArray呢? BitArray总是可以用于很好的功能,例如“爆炸”到Enumerable,而C#已经内置了合适的字节位操作。

假设一个更一般的情况,即数据是8位对齐的......但是有一些未确定的长度

这实际上比在BitArray中“每个项目”做得更好(更快,更有效等)吗? 我不知道,但怀疑不是。我肯定会从“简单”方法开始 - 这只是一个概念验证,并且可能(或可能不是)在基准测试中进行比较。无论如何,先写清楚 ......以下不是它! (其中至少有一个错误 - 我责怪额外的复杂性; - )

byte reverse (byte b) { 
    byte o = 0;
    for (var i = 0; i < 8; i++) {
        o <<= 1;
        o |= (byte)(b & 1);
        b >>= 1;
    }
    return o;
}

byte[] table;
BitArray reverse8 (BitArray ar) {
    if (ar.Count % 8 != 0) {
        throw new Exception("no!");
    }

    byte[] d = new byte[ar.Count / 8];
    ar.CopyTo(d, 0);

    // this only works if the bit array is
    // a multiple of 8. we swap bytes and
    // then reverse bits in each byte
    int mid = d.Length / 2; 
    for (int i = 0, j = d.Length - 1; i < mid; i++, j--) {
        byte t = d[i];
        d[i] = table[d[j]];
        d[j] = table[t];
    }

    return new BitArray(d);
}

string tostr (BitArray x) {
    return string.Join("",
        x.OfType<bool>().Select(i => i ? "1" : "0").ToArray());
}

void Main()
{
    table = Enumerable.Range(0,256).Select(v => reverse((byte)v)).ToArray();
    {
        byte[] s = new byte[] { 1, 0xff };  
        BitArray ar = new BitArray(s);  
        // linqpad :)
        tostr(ar).Dump();
        tostr(reverse8(ar)).Dump();
    }
    "--".Dump();
    {
        byte[] s = new byte[] { 3, 42, 19 };
        BitArray ar = new BitArray(s);  
        // linqpad :)
        tostr(ar).Dump();
        tostr(reverse8(ar)).Dump();
    }   
}

输出:

1000000011111111
1111111100000001
--
110000000101010011001000
000100110101010000000011

expr.Dump()LINQPad功能。

答案 5 :(得分:0)

改编自@TimLoyd 的答案,并将其变成了一个更易于使用的扩展。

public static BitArray Reverse(this BitArray array)
{
    int length = array.Length;
    int mid = (length / 2);

    for (int i = 0; i < mid; i++)
    {
        bool bit = array[i];
        array[i] = array[length - i - 1];
        array[length - i - 1] = bit;
    }

    return new BitArray(array);
}

用法:

var bits = new BitArray(some_bytes).Reverse();