10

C# で BitArray の順序を逆にする最も効率的な方法は何かと考えていました。明確にするために、.Not() を呼び出して Bitarray を逆にしたくありません。配列内のビットの順序を逆にしたいのです。

乾杯、クリス

4

6 に答える 6

35
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;
    }    
}
于 2011-01-25T08:18:14.630 に答える
9

長い配列と比較的少数の用途の場合は、それをラップするだけです。

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

    }
于 2011-01-25T08:33:17.930 に答える
6

これは、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
于 2012-05-03T21:17:40.793 に答える
3
 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)
于 2012-05-17T10:45:52.840 に答える
1

サイズが8ビットに固定されている場合、下からの「テーブル」ルックアップだけで十分であるため、プレーンを処理する場合byte、ルックアップがおそらく最も速い方法です。ただし、データを取得/設定するための BitSet の余分なオーバーヘッドにより、ルックアップの利点が無効になる場合があります。また、初期ビルド コストと永続的なオーバーヘッドも考慮する必要があります (ただし、値は配列リテラルにコード化できます ... いけない!)

一方、データが8 ビット (これまで)しかなく、「パフォーマンスが重要」である場合、なぜ BitArray を使用するのでしょうか? BitArray は、Enumerable への "爆発" などの優れた機能に常に使用できますが、C# には適切なバイト ビット操作が既に組み込まれています。

データが 8 ビットでアラインされているというより一般的なケースを想定しています...しかし、長さは未定です

これは、BitArray で「アイテムごと」に行うよりも実際に優れていますか (高速、効率的など)? 私にはわかりませんが、そうではないと思います。私は間違いなく「単純な」方法から始めます.これは概念実証としてここにあり、ベンチマークで比較するのは興味深いかもしれません. とにかく、最初に明確にするために書いてください...そして以下はそうではありません! (少なくとも 1 つのバグがあります -- 余分な複雑さが原因だと思います ;-)

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の機能です。

于 2011-01-25T08:50:16.320 に答える