我有一个字节数组,如下所示
byte[] arrByt = new byte[] { 0xF, 0xF, 0x11, 0x4 };
所以在二进制 arrByt = 00001111 00001111 00010001 000000100
现在我想从arrByt中删除每个字节的前导0,创建一个新的字节数组。
arrNewByt = 11111111 10001100 = { 0xFF, 0x8C };
我知道可以通过将字节值转换为二进制字符串值,去掉前面的0,将值追加,然后再转换回字节值到新的数组中,然而对于一个大数组来说,这个过程很慢。
有没有更快的方法来实现这个目标(比如逻辑运算,位运算,或者其他有效的方法)?
谢谢,我有一个字节数组,如下图所示。
这应该可以很快地完成工作。至少只有标准的循环和运算符。试试吧,对于较长的源数组也能用。
// 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
如果你想找到最重要位的位置,你可以对字节进行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;
请检查这段代码 这也许会对你有所帮助。
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"));
}