去除字节数组中的前导符0。

问题描述 投票:1回答:1

我有一个字节数组,如下所示

byte[] arrByt = new byte[] { 0xF, 0xF, 0x11, 0x4 };

所以在二进制 arrByt = 00001111 00001111 00010001 000000100

现在我想从arrByt中删除每个字节的前导0,创建一个新的字节数组。

arrNewByt = 11111111 10001100 = { 0xFF, 0x8C };

我知道可以通过将字节值转换为二进制字符串值,去掉前面的0,将值追加,然后再转换回字节值到新的数组中,然而对于一个大数组来说,这个过程很慢。

有没有更快的方法来实现这个目标(比如逻辑运算,位运算,或者其他有效的方法)?

谢谢,我有一个字节数组,如下图所示。

c# arrays bit-manipulation
1个回答
1
投票

这应该可以很快地完成工作。至少只有标准的循环和运算符。试试吧,对于较长的源数组也能用。

// source array of bytes
var arrByt = new byte[] {0xF, 0xF, 0x11, 0x4 };

// target array - first with the size of the source array
var targetArray = new byte[arrByt.Length];

// bit index in target array
// from left = byte 0, bit 7 = index 31; to the right = byte 4, bit 0 = index 0
var targetIdx = targetArray.Length * 8 - 1;

// go through all bytes of the source array from left to right
for (var i = 0; i < arrByt.Length; i++)
{
    var startFound = false;

    // go through all bits of the current byte from the highest to the lowest
    for (var x = 7; x >= 0; x--)
    {
        // copy the bit if it is 1 or if there was already a 1 before in this byte
        if (startFound || ((arrByt[i] >> x) & 1) == 1)
        {
            startFound = true;

            // copy the bit from its position in the source array to its new position in the target array
            targetArray[targetArray.Length - ((targetIdx / 8) + 1)] |= (byte) (((arrByt[i] >> x) & 1) << (targetIdx % 8));

            // advance the bit + byte position in the target array one to the right
            targetIdx--;
        }
    }
}

// resize the target array to only the bytes that were used above
Array.Resize(ref targetArray, (int)Math.Ceiling((targetArray.Length * 8 - (targetIdx + 1)) / 8d));

// write target array content to console
for (var i = 0; i < targetArray.Length; i++)
{
    Console.Write($"{targetArray[i]:X} ");
}

// OUTPUT: FF 8C

0
投票

如果你想找到最重要位的位置,你可以对字节进行log2()(如果你没有log2,你可以使用log(x)log(2),这和log2(x)是一样的)。

例如,数字7、6、5、4的第3位位置都有一个 "1"(0111、0110、0101、0100)。它们的log2()都在2到2.8之间。同样的事情发生在第4位的任何东西上,它将是一个介于3和3.9之间的数字。所以你可以通过在数字的log2()上加1来找出最重要的位(四舍五入)。

floor(log2(00001111)) + 1 == floor(3.9) + 1 == 3 + 1 == 4

你知道一个字节有多少位,所以你可以很容易地知道左移的位数。

int numToShift = 8 - floor(log2(bytearray[0])) + 1;
shiftedValue = bytearray[0] << numToShift;

从这里开始,你只需要跟踪你有多少个未完成的比特(还没有推到字节数组中),然后把它们全部推上去。

上面的代码只对第一个字节数组有效。如果你把它放在一个循环中,numToShift可能需要跟踪最新的空槽来将东西移入(你可能需要向右移动以适应当前的字节数组,然后用剩余的部分放入下一个字节数组的开始)。所以,在上面的代码中,你也许不会做 "8-",而是会把起始位置。例如,如果当前字节数组中只剩下3个位来填充,你会这样做。

int numToShift = 3 - floor(log2(bytearray[0])) + 1;

所以这个数字应该是一个变量

int numToShift = bitsAvailableInCurrentByte - floor(log2(bytearray[0])) + 1;

0
投票

请检查这段代码 这也许会对你有所帮助。

        byte[] arrByt = new byte[] { 0xF, 0xF, 0x11, 0x4 };
        byte[] result = new byte[arrByt.Length / 2];

        var en = arrByt.GetEnumerator();

        int count = 0;
        byte result1 = 0;
        int index = 0;
        while (en.MoveNext())
        {
            count++;
            byte item = (byte)en.Current;

            if (count == 1)
            {
                while (item < 128)
                {
                    item = (byte)(item << 1);
                }
                result1 ^= item;
            }

            if (count == 2)
            {
                count = 0;
                result1 ^= item;

                result[index] = result1;
                index++;
                result1 = 0;
            }
        }

        foreach (var s in result)
        {
            Console.WriteLine(s.ToString("X"));
        }
© www.soinside.com 2019 - 2024. All rights reserved.