Сдвиг битового массива

В настоящее время я пытаюсь сдвинуть BitArray, сохраняя при этом его длину. Поскольку встроенного метода нет, я изо всех сил пытаюсь его создать, но, к сожалению, не могу заставить его работать.

Мой исходный код BitArray устанавливает длину 421 для BitArray.

var b = new BitArray(length: 421);

Затем я присваиваю некоторые значения для тестирования. Например: b.Set(0, true); б. Установить (1, правда);

Однако я не могу понять, как сдвинуть битовый массив. Попытки: - Я думал, что смогу преобразовать его в длинный, а затем произвести битовую манипуляцию. Однако long не соответствует моей точной длине BitArray, что впоследствии приводит к ошибкам, когда я применяю побитовые операции к двум BitArray (мои полные требования: (array1 |= array2 >> 20). — Я пытался преобразовать BitArray в byte[ ], выполните манипуляцию и верните ее (см. Битовый сдвиг N бит):

    public static byte[] ToBytesArray(this BitArray array, int startIndex, int count)
    {
        // Get the size of bytes needed to store all bytes
        int bytesize = count / ByteLength;

        // Any bit left over another byte is necessary
        if (count % ByteLength > 0)
        {
            bytesize++;
        }

        // For the result
        byte[] bytes = new byte[bytesize];

        // Must init to good value, all zero bit byte has value zero
        // Lowest significant bit has a place value of 1, each position to
        // to the left doubles the value
        byte value = 0;
        byte significance = 1;

        int bytepos = 0;
        int bitpos = startIndex;

        while (bitpos - startIndex < count)
        {
            // If the bit is set add its value to the byte
            if (array[bitpos])
                value += significance;

            bitpos++;

            if (bitpos % ByteLength == 0)
            {
                // A full byte has been processed, store it
                // increase output buffer index and reset work values
                bytes[bytepos] = value;
                bytepos++;
                value = 0;
                significance = 1;
            }
            else
            {
                // Another bit processed, next has doubled value
                significance *= 2;
            }
        }

        return bytes;
    }

    public static BitArray ShiftLeft(this BitArray array, int bitcount)
    {
        byte[] value = array.ToBytesArray();
        byte[] temp = new byte[value.Length];
        if (bitcount >= 8)
        {
            Array.Copy(value, bitcount / 8, temp, 0, temp.Length - (bitcount / 8));
        }
        else
        {
            Array.Copy(value, temp, temp.Length);
        }

        if (bitcount % 8 != 0)
        {
            for (int i = 0; i < temp.Length; i++)
            {
                temp[i] <<= bitcount % 8;
                if (i < temp.Length - 1)
                {
                    temp[i] |= (byte)(temp[i + 1] >> 8 - bitcount % 8);
                }
            }
        }

        return new BitArray(temp);
    }

Однако длина байта составляет 8 байт, что тоже не подходит для моей длины. В результате получается 416 или 424 (еще один байт) вместо 421.

  • Наконец, я попробовал "примитивный" способ:

        for (int i = 0; i < bitcount; i++)
        {
            var lastValue = array[0];
            for (var j = 0; j < array.Length - 1; j++)
            {
                array[j] = array[j + 1];
            }
    
            array[array.Length - 1] = lastValue;
        }
    

Я также проверяю SO (например, BitArray - Shift bits), но у меня ничего не получилось.

Любая помощь будет очень признательна!


person OzB    schedule 31.08.2014    source источник
comment
не уверен на 100%, в чем проблема и как эти ссылки не ответили на нее. Вам нужен массив, который вы можете сдвигать влево и вправо (я предполагаю, что при сдвиге добавляется 0) или циклический (так что, если вы сдвинетесь вправо, и у вас есть 1 на краю, он переместится в начало? )   -  person Noctis    schedule 01.09.2014
comment
Возможно, вы сталкиваетесь с путаницей между арифметическими (крайний левый бит, заполненный знаком) и логическими (самый левый бит, заполненный нулями) сдвигами битов? Согласно MSDN, характер левого операнда (целочисленный тип со знаком или без знака) определяет, что происходит в соответствии со спецификацией С#. Обратите внимание, что спецификация C++ оставляет предписание зависящим от реализации. msdn.microsoft.com/en-us/library/xt18et0d.aspx   -  person Pieter Geerkens    schedule 01.09.2014
comment
@Noctis - я хочу нециклическую операцию. Я конвертирую реализацию на С++, используя std::bitset в .NET. Я не думаю, что это проблема в моем случае, поскольку стандартные примитивные типы, такие как int или unit, не могут мне помочь, поскольку мне нужна нестандартная длина битового массива. Моя цель — преобразовать C++ std::bitset operator›› и ‹‹ в .NET с помощью BitArray.   -  person OzB    schedule 01.09.2014


Ответы (1)


Все еще не уверен на 100%, в чем проблема. Вот наивная реализация:

void Main()
{
    // Creates and initializes a BitArrays of size 7 (you have 421).
    bool[] myBools = new bool[7] { true,false,false,true,true,false,true };
    BitArray myBA1 = new BitArray(myBools );

    PrintBitArray(myBA1);              // 1001101
    PrintBitArray(ShiftRight(myBA1));  // 0100110
    PrintBitArray(ShiftLeft (myBA1));  // 0011010
}

BitArray ShiftRight(BitArray aSource) {
    bool[] new_arr  = new bool[( aSource.Count)];
    for (int i = 0; i < aSource.Count -1; i++)
        new_arr[i+1] = aSource[i];

    return new BitArray(new_arr);
}   

BitArray ShiftLeft(BitArray aSource) {
    bool[] new_arr  = new bool[( aSource.Count)];
    for (int i = 0; i < aSource.Count -1; i++)
        new_arr[i] = aSource[i+1];

    return new BitArray(new_arr);
}

string PrintBitArray(BitArray aSource) {
    StringBuilder sb  = new StringBuilder();
    foreach (var bit in aSource)
    {
        sb.Append( (bool)bit ? 1 : 0 );
    }
    return sb.ToString();
}

Обратите внимание, как биты копируются в циклах, и что третий PrintBitArray выполняется на исходном входе, а не на выходе второго.

person Noctis    schedule 31.08.2014