Кодирование / декодирование десятичных значений в двоичных блоках с переменной битовой шириной

Я пытаюсь создать двоичный кодер / декодер с переменной битовой шириной для протокола в персональном сетевом проекте, который я разрабатываю … и мой тупой мозг полностью запутался в том, как понять двоичное кодирование / декодирование с переменной битовой пропускной способностью. Я смотрю на тот же ~ 18 SLOC уже около четырех дней, и я все еще чувствую себя совершенно вне себя. Я чувствую, что должен быть в состоянии понять это, но, к сожалению, мой мозг случайным образом отключается, когда я пытаюсь отследить различные числовые отношения 🙁

Теоретически, то, что я хочу сделать, невероятно просто. Я объявляю список битовых полос и значение, которое я хочу сохранить в этой битовой полосе, например:

[10 bits]: 1013
[1  bit ]: 1
[2  bits]: 3
[19 bits]: 51209

Принимая во внимание битовую ширину, значения будут последовательно упорядочены в двоичную строку следующим образом:

               1 bit
| 2 bits
| ||
/-10 bits--\ | \/ /------ 19 bits ------\
12345678  12 3 45 678  12345678  12345678
11111101  01 1 11 000  11001000  00001001
\----------/ | \/ \---------------------/
1012     1  3          51209

Поток битов, выделенный жирным шрифтом выше, — это то, что я передаю по проводам:

11111101  253  FD
01111000  120  78
11001000  200  C8
00001001    9  09

На другом конце я отображаю список {10, 1, 2, 19} (набор битовых полос обозначен вверху) в зависимости от последовательности байтов, которые я получил, что оставляет мне исходный набор значений, которые я хотел передать.

Хотя это, в основном, общий алгоритмический вопрос, и семантика любого конкретного языка, возможно, не имеет значения, я должен упомянуть, что я использую PHP для этого — и одна из причин, по которой я так застрял, состоит в том, что я пытаюсь решить как избежать обращения к строковым манипуляциям, которые PHP, похоже, одержимо склоняет к тому, чтобы поощрять предпочтение перед правильной числовой обработкой. Однако эта функция (надеюсь) будет обрабатывать данные на скоростях от 2 до 3 цифр-Мбит / с, и я хочу, чтобы подпрограммы были максимально быстрыми. (Кстати, я бы использовал другой язык, но PHP я знаю больше всего> _>)

Я понимаю основы двоичного кода, и я должен подчеркнуть, что у меня действительно есть работающий кодер, я думаю (он выводит двоичные данные в обратном направлении) — но я понятия не имею, что я здесь делаю. Я не спрашиваю «как мне написать эту функцию», я спрашиваю «какова структурная механика того, что я делаю, и как мне вообще это понять».

Я должен также отметить, что эта проблема не является замаскированным домашним заданием; это для компонента сетевой библиотеки в персональном программном проекте, который я проектирую, который, я надеюсь, научит меня сетевым технологиям, обработке событий и параллелизму. Надеюсь, я смогу понять все другие вещи, которые мне нужно будет реализовать … LOL

2

Решение

Чтобы дать вам небольшую отправную точку, как такой двоичный декодер / кодировщик может выглядеть вот как пример:

Итак, что же это за концепция?

Довольно просто я перебираю все данные, которые вы хотите отправить, и разделяю их на отдельные байты. Итак, в качестве примера:

data:    1013
bitMask:   10

Поэтому я сначала вычисляю, сколько байтов требуется для его отправки. Здесь это будет 2 байта 8 бит на байт.

После всех подготовительных работ и вычислений легко отправлять все данные побайтно и побитно! Так что, если мы возьмем пример сверху, это будет выглядеть примерно так:

data:    1013  -> 0000'0011 1111'0101
bitMask:   10

total amount of bytes: 2
1. byte = 1111'0101
2. byte = 0000'0011

Таким образом, при отправке данных (здесь вывод в браузере) вы отображаете данные в обратном порядке! Потому что, когда вы получаете его, вы меняете его обратно и получаете правильные результаты!

<?php

class binaryCoder {

/* Properties */
public $data;  // <-- save/receive data into this property
public $bitMask = [];
private $byteCount = 0x00;

/* Constructor */
public function __construct() {}

/* Methods */
public function writeData(array $data, array $bitMask) {

$this->data = $data;
$this->bitMask = $bitMask;
$this->byteCount = array_reduce($this->bitMask, function($byteCount, $bits){
return $byteCount + ceil($bits/8);
}, 0x00);foreach(array_combine($this->bitMask, $this->data) as $mask => $data) {
for($byteCounter = 0; $byteCounter < ceil($mask/8); $byteCounter++) {
$this->writeByte($data >> ($byteCounter*8));
}
}

}

public function readData(array $bitMask) {
$this->bitMask = $bitMask;
$byte = 0x00;foreach($this->bitMask as $key => $mask) {
$message[$key] = "";
for($byteCounter = 0; $byteCounter < ceil($mask/8); $byteCounter++, $byte++) {
$message[$key] = sprintf("%08d", $this->readByte($byte*8)) . $message[$key];
}
}

$message = array_map("bindec", $message);
print_r($message);

}

private function writeByte($byte) {
for($bitCount = 0; $bitCount < 8; $bitCount++) {
$this->writeBit((bool)($byte & (1 << $bitCount)));
}
}

private function readByte($bytePosition) {
$byte = 0x00;

for($bitCount = 0; $bitCount < 8; $bitCount++) {
$byte |= (int)$this->readBit($bytePosition+$bitCount) << $bitCount;
}
return decbin($byte);
}

private function writeBit($bit) {
echo ($bit?1:0);  // --> send/write data to dest. (Note it's reversed!)
}

private function readBit($bit) {
return $this->data[$bit];
}}/* Testing */
$binaryTransmitter = new binaryCoder();
$binaryTransmitter->writeData([1013, 1, 3, 51209], [10, 1, 2, 19]);
$binaryTransmitter->data = "10101111110000001000000011000000100100000001001100000000";  //received data
$binaryTransmitter->readData([10, 1, 2, 19]);

?>

выход:

10101111110000001000000011000000100100000001001100000000 //note output here is reversed!
Array ( [0] => 1013 [1] => 1 [2] => 3 [3] => 51209 )
2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]