#c #bytearray #bit-manipulation
#c #массивы #манипулирование битами
Вопрос:
У меня возникла небольшая проблема при попытке переместить группы из 17-битных данных в байтовый массив. Я не хочу проходить пошагово, но я не могу разобраться в логическом цикле.
Мне это нужно таким образом, потому что я должен вычислять контрольную сумму путем сложения всех байтовых значений после их объединения таким образом.
Итак, вот с чем я борюсь.
У меня есть 16-байтовые массивы. Первые 3 байта массива содержат 17 бит, которые мне нужны. (8 бит из [0]
, 8 бит из [1]
и MSB из [2]
.)
Мне нужно переместить эти 16 17-битных значений в один отдельный байтовый массив.
Первый из них прост:
int index = 0;
myArray[index ] = driverData[driver][0]; //First byte
myArray[index ] = driverData[driver][1]; //Second byte
myArray[index] = (driverData[driver][2] amp; 0x80) << 7; //First bit of the third byte.
Отсюда, однако, становится все труднее пытаться выполнить какой-либо цикл для их перемещения.
driver ;<br>
//Take the 7 MSBs from the data array.
myArray[index ] |= (byte)(driverData[driver][0] amp; 0x7e >> 1);
//This leaves a single bit left over on driverData[driver][0].
myArray[index] = (byte)(driverData[driver][1] amp; 0x1 << 7);
Я думаю, вы поняли картину. Я все это делаю неправильно? Кто-нибудь может указать мне правильное направление?
Комментарии:
1. (надеюсь, я не слишком сильно испортил вашу текущую правку, извините 🙂 Я думаю, что на самом деле это может быть проще с
driverData[driver][1]
конструкцией, чем сdata1
конструкциейdata2
,driver
, поскольку затем вы также можете выполнить итерацию по, а также. (Также обратите внимание, что в описании говорится[1]
,[2]
[3]
,[0]
, но в коде говорится[1]
,[3]
,,,.)2. Нет, вы его значительно улучшили, спасибо. Я быстро исправлю эти проблемы. Спасибо.
3. сарнольд… Я понятия не имею, как вы его отформатировали с выделенным кодом и т.д… Думаю, я только что уничтожил ваши превосходные правки.
4. Итак, просто для ясности, первые три байта каждого входного массива содержат 17 бит информации. И вы должны упаковать эти группы из 17 бит последовательно в байтовый массив? Итак, 1-й байт выходных данных содержит 1-е 8 бит 1-го массива, 2-й байт выходных данных содержит 2-е 8 бит 1-го массива, 3-й байт выходных данных содержит последний бит 1-го массива и 1-е 7 бит 2-го массива и так далее?
5. Да, квантовая механика. Это точно.
Ответ №1:
Похоже, у вас цикл с простыми числами, достаточно большой, чтобы сделать кодирование отдельных случаев плохой идеей. Это классическая проблема упаковки. Вам нужен цикл, который повторяет ваш пункт назначения, и некоторый внутренний код, который получает больше битов для упаковки. Ваш упаковочный код должен знать, сколько битов доступно для него с последней итерации, сколько ему нужно, и должен иметь возможность увеличивать указатель источника, если его недостаточно.
Комментарии:
1. Хорошо, итак, как бы вы это кодировали?
2. @Spenduku: будет проще, если вы будете делать это по одному биту за раз. Удалите 17 бит из очереди ввода, поставьте в очередь 17 бит на выходе. Обе стороны должны отслеживать текущий байт и текущий бит внутри этого байта.
3. Я должен поблагодарить вас, bk1e, поскольку ваш комментарий, казалось, подсказал, как этого добиться.
Ответ №2:
Хорошо, похоже, это работает. Вероятно, мне нужно протестировать это еще раз, но, похоже, это дает мне результат, которого я пока ожидаю. Я уверен, что мог бы сделать это как-то лучше.
// ... //
void foo()
{
//Lets start by getting all the 17bit values from each driver for the board.
int bitIndex = 7;
int byteIndex = 0;
int stopIndex = chipIndex GetChipCount();
//Now we start the shiftyness.
for (int driver = chipIndex; driver < stopIndex; driver ) {
int userBits =
(driverData[driver][0] amp; 0xff) << 9 | (driverData[driver][1]
amp; 0xff)
<< 1 | (driverData[driver][2] amp; 0x80) >> 7;
AddBitsToArray(userBits, ref bitIndex, ref byteIndex);
}
}
/// <summary>
/// Takes the 17 bits, and adds them to the byte array.
/// </summary>
private void AddBitsToArray(int userBits, ref int bitIndex, ref int byteIndex)
{
int bitCount = 17;
while (bitCount > 0) {
//First 8 bytes.
checksumBytes[byteIndex] |=
(byte) (((userBits amp; bitValue(bitCount - 1)) >>
(bitCount - 1)) << bitIndex);
//Move up the bit index to be written to.
bitIndex--;
//Decrement the number of bits left to shift.
bitCount--;
//If we have gone past the 8th bit, reset the bitIndex and increment the byteIndex.
if (bitIndex >= 0)
continue;
bitIndex = 7;
byteIndex ;
}
}
/// <summary>
/// Returns the value of a single bit at the given index.
/// </summary>
private int bitValue(int bitIndex)
{
return (int)(Math.Pow(2, bitIndex));
}
Комментарии:
1. Это чище, чем все, что я придумал 🙂 если он пройдет ваши тесты, я бы сказал, будьте довольны этим. 🙂
2. Хорошо, будет сделано. Спасибо за вашу помощь в редактировании, сарнольд. 🙂 Похоже, что код JYeltons тоже отлично работает, жаль, что я не могу выбрать два ответа
Ответ №3:
Вот что я придумал. Первая часть метода — это просто настройка некоторых поддельных входных данных, поэтому удалите это и добавьте аргументы по мере необходимости. OutputData
Массив излишне большой, но я не тратил время на вычисление его фактической длины.
Я использовал 170 в качестве входного значения, которое является 10101010
и было полезно при проверке.
private void BitShift17()
{
const int NumChunks = 16;
byte[] DriverData = new byte[]
{
170,
170,
170
};
byte[][] InputData = new byte[NumChunks][];
for (int n = 0; n < NumChunks; n )
InputData[n] = DriverData;
byte[] OutputData = new byte[NumChunks * 3]; // Unnecessarily large
int OutputIndex = 0;
int BitPosition = 0;
for (int Driver = 0; Driver < InputData.Length; Driver )
{
for (int InputIndex = 0; InputIndex < 3; InputIndex )
{
byte InputByte = InputIndex == 2 ? (byte)(InputData[Driver][InputIndex] amp; 128) : InputData[Driver][InputIndex];
if (BitPosition == 0)
{
OutputData[OutputIndex] = InputByte;
if (InputIndex == 2)
BitPosition ;
else
OutputIndex ;
}
else
{
if (InputIndex == 2)
{
OutputData[OutputIndex] |= (byte)(InputByte >> BitPosition);
BitPosition ;
}
else
{
OutputData[OutputIndex] |= (byte)(InputByte >> BitPosition);
OutputIndex ;
OutputData[OutputIndex] = (byte)(InputByte << 8 - BitPosition);
}
}
}
if (BitPosition > 7) BitPosition = 0;
}
}
Комментарии:
1. Хммм… Я тоже проверю это и посмотрю, что у меня получится. На мгновение слишком поздно! 🙂 Спасибо Джелтону.
2. Я пометил ваш ответ как правильный, поскольку вы тоже приложили усилия. Еще раз спасибо.