Эффективная конкатенация

#c #bit-manipulation #concatenation #bitwise-operators

#c #битовая манипуляция #конкатенация #побитовые операторы

Вопрос:

Я пытаюсь отправить сообщение через LPWAN, и одна из проблем, с которыми я сталкиваюсь, — это попытка сделать мое сообщение как можно короче.

Например:

У меня есть два целых числа (0-100) и два логических значения, которые я должен преобразовать в шестнадцатеричное значение для отправки через LPWAN. Пример:

  • 24
  • 63
  • Верно
  • Ложь

Когда я объединяю это как 246310 (Hex:3C226), это займет 3 байта. Однако я знаю, что мое первое целое число никогда не будет больше 50, то есть всего 6 бит. Могу ли я сделать шестнадцатеричное сообщение короче, чем 3C226?

Комментарии:

1. @LPs Они всегда состоят из 2 целых чисел и 2 логических значений, первое целое число всегда равно от 0 до 50, а второе целое число всегда от 0 до 100

2. В своем комментарии вы указываете, что второе целое число находится в диапазоне [0, 100], но в вашем вопросе это [0, 80]. Пожалуйста, отредактируйте свой вопрос, если он на самом деле [0, 100].

3. Кроме того, если между этими переменными нет каких-либо зависимостей, вам всегда будут нужны по крайней мере ceil(log(51 * 101 * 2 * 2) / log(2)) = 15 биты для отправки этих сообщений. ответ unwind в этом случае максимально эффективен, и с ним также довольно легко работать.

4. сделано, хотя это не имеет значения для вопроса, поскольку 100 равно 7 битам, как и 80

5. Это почти изменило ситуацию. Если у вас есть диапазоны [0, 50], [0, 79], [0, 1], [0, 1], вам понадобится не менее 14 бит, если вы используете другую технику.

Ответ №1:

Да, это должно быть возможно.

Количество битов для ваших полей равно:

  • integer0 : Целое число 0..50, 6 бит.
  • integer1 : Целое число 0..80, 7 бит.
  • flag0 : Логическое значение, 1 бит.
  • flag1 : Логическое значение, 1 бит.

Таким образом, это в общей сложности 6 7 1 1 = 15 бит.

Вот как кодировать:

  -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
|15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
|  |                 |                    |  |  |
|  |  integer0       |  integer1          |f0|f1|
 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 

uint16_t encode(uint8_t integer0, uint8_t integer1, bool flag0, bool flag1)
{
  return ((uint16_t) integer0 << 9) | ((uint16_t) integer1 << 2) | ((uint16_t) flag0 << 1) | flag1;
}
 

Ответ №2:

Используя 2 байта, значение может быть сохранено в виде:

    FirstNum         Second        1st bool     2nd bool
<------------> <------------> <------------> <------------>
     6bits          7bits          1bit          1bit
 

У вас все еще остается 1 бит.

Используйте left shift операцию << для достижения вышеуказанного.