【问题标题】:Most efficient way to reverse the order of a BitArray?反转BitArray顺序的最有效方法?
【发布时间】:2011-06-15 00:58:58
【问题描述】:

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

干杯, 克里斯

【问题讨论】:

  • 向后使用(阅读)怎么样?
  • 是的,大小是固定的(8位)

标签: c# bitarray


【解决方案1】:
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;
    }    
}

【讨论】:

  • 请将此添加到某人的官方dotnet代码中
【解决方案2】:

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

    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; }
        }

    }

【讨论】:

  • +1 不错。在某些情况下,这不是真正的答案,而是聪明的选择。
【解决方案3】:

因为如果将大小固定为 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 功能。

【讨论】:

    【解决方案4】:

    这将是最好的方法 在 for 循环中使用 XOR 来反转任何长度的 MSB 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
    

    【讨论】:

    • 您将内存消耗和分配操作增加三倍。这怎么能有效率?
    【解决方案5】:
     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)
    

    【讨论】:

      【解决方案6】:

      改编自@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();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-10-09
        • 2023-03-29
        • 2012-07-21
        • 2015-11-29
        • 1970-01-01
        • 2013-06-25
        • 1970-01-01
        相关资源
        最近更新 更多