Циклические коды: кодирование через многочлены и деление с остатком
Каждый Ethernet-кадр проходит проверку CRC — это деление многочлена на многочлен над полем из двух элементов. Разбираем порождающий многочлен, кодирование и синдром остатка.
Каждый кадр Ethernet несёт в хвосте четыре байта CRC-32; тот же приём охраняет ZIP-архивы и PNG-файлы. Приёмник делает одну операцию — делит принятое слово на заранее известный многочлен — и по остатку выносит вердикт: канал чистый или в данных дыра. Никаких проверочных битов на степенях двойки, как в коде Хэмминга, — вся механика свелась к школьному делению уголком, только в арифметике из нулей и единиц. За этим лаконизмом стоит целый класс — циклические коды, и в нём живут все рабочие лошадки связи: CRC, коды БЧХ, Рида—Соломона в QR-кодах и на компакт-дисках.
Слова как многочлены#
Битовая строка записывается многочленом с коэффициентами 0 и 1, старший бит — старшая степень: слово — это . Сдвиг строки влево на один разряд — умножение на . Сложение многочленов — поразрядный XOR, потому что все вычисления идут в поле , где : минус и плюс неотличимы, вычитание — то же сложение. Умножение — обычное школьное, с приведением по модулю 2.
В этом языке циклический код длины определяется одним предложением: это множество многочленов степени меньше , кратных фиксированному порождающему многочлену степени , причём обязан делить . Число проверочных символов равно степени , информационных — ; код обозначается . Требование выглядит техническим, а отвечает за главную фишку: циклический сдвиг любого кодового слова снова кодовое слово. Доказательство в одну строку: сдвиг — это умножение на с заворотом старшего бита, то есть ; оба слагаемых кратны (второе — потому что ), значит, кратность сохраняется.
Кодирование: умножение или деление#
Два способа превратить информационный многочлен степени меньше в кодовое слово. Несистематический: просто умножить, — быстро, но данные перемешиваются с проверками, прочитать исходное сообщение в кодовом слове глазами не выйдет. Систематический — рабочий: припишем нулей справа от сообщения, поделим с остатком:
Кодовое слово кратно по построению — именно поэтому приёмник, поделив принятое на , при отсутствии ошибок получит ноль в остатке. Любой сбой в канале портит кратность, и остаток «звенит». Множитель — это просто нулевых позиций, зарезервированных под проверки; данные стоят в слове открыто, как и в коде Хэмминга.
Полный пример: код (7,4) с порождающим $x^3 + x + 1$#
Многочлен делит — проверяется делением уголком за четыре шага, — значит, из него выходит циклический код с тремя проверочными битами. Оказывается, это циклическая версия хэмминговского : те же 16 кодовых слов, та же способность чинить одиночную ошибку, только устройство кодировщика несравнимо проще — один регистр сдвига с парой XOR-элементов. Закодируем сообщение , то есть .
Теперь пустим слово по испорченному каналу. Пусть сбой перевернул бит при : принято , двоично . Приёмник делит на и получает остаток — не ноль, тревога. Красиво то, что остаток зависит только от разности: , поскольку часть делится нацело. Остаток — подпись ошибки, тот же синдром, что и в коде Хэмминга, только вычисленный делением: вектор ошибки веса один даёт остаток, равный остатку от деления на .
Синдромы одиночных ошибок для легко выписать заранее: , , , , , , — все семь различны, поэтому одиночная ошибка не просто обнаруживается, а локализуется по позиции. Это ровно условие : код исправляет одну ошибку и обнаруживает две, как и всякий код с минимальным расстоянием 3 из таблицы урока Хэмминга.
Почему класс такой живучий#
Аппаратная цена кодирования и проверки смехотворна: сдвиговый регистр из ячеек, между которыми вкручены XOR-сумматоры согласно коэффициентам , — за тактов регистр и содержит остаток. В приёмнике это считанные такты, в передатчике — тоже; программная реализация — таблица из 256 предвычисленных байтов. Ни один универсальный код не даёт проверки дешевле, чем «деление на константу».
Теория обещает больше, чем удобство. Многочлены вида раскладываются в произведение неприводимых над множителей, и выбор как произведения нескольких из них — это конструктор: набрали множители с нужными корнями — получили гарантированное минимальное расстояние кода. Так рождаются коды БЧХ: при аккуратном выборе код исправляет две ошибки, — три, а расширенные семейства доходят до десятков. Коды Рида—Соломона — родственники того же класса над полем из 256 элементов: именно они позволяют царапанному диску звучать как новым и QR-коду читаться с трети площади.
CRC — усечённый родственник циклических кодов: он не исправляет, а только обнаруживает, зато находит всё подряд. Стандартный полином CRC-32 (Ethernet, ZIP) — . Теоретическая гарантия поражает: любая одиночная и двойная ошибка, любая ошибка нечётного веса (благодаря множителю в составе полинома), любой взрыв ошибок длиной до 32 подряд. Для каналов, где ошибки приходят пачками (щелчок по проводу портит соседние биты), это именно то, что нужно.
Пара деталей, на которых спотыкаются. Первая: вычитание в — это сложение, знак остатка ни на что не влияет, но студенты упорно «минусуют» и получают минус перед одночленом, которого в поле не бывает. Вторая: не забыть про множитель — кодировать сообщение без приписанных нулей значит забыть место под проверки. Третья: проверка — если после очередного XOR старшая степень остатка не упала ниже степени делителя, деление не закончено. Арифметика многочленов — та же индуктивная техника, что в рекуррентных соотношениях: каждый шаг опирается на предыдущий, и ошибка шага съедает весь остаток.
- Слово — многочлен над ; циклический код — кратные степени , где ,
- Систематическое кодирование:
- Проверка на приёмнике — деление на ; ненулевой остаток = обнаруженная ошибка, остаток — её подпись
- CRC-32 ловит одиночные, двойные, нечётные и пачечные ошибки до 32 бит; БЧХ и Рида—Соломона исправляют больше
Кодирование систематическим циклическим кодом сводится к операции...
Приёмник получил слово, кратное , но с перевёрнутыми двумя битами. Что покажет проверка?
Почему код называется циклическим?
Частые вопросы
Чем циклический код (7,4) лучше кода Хэмминга?
Это тот же код по множеству слов — те же 16 кодовых слов, то же расстояние 3. Разница в реализации: проверки Хэмминга требуют трёх независимых групп XOR, а циклическая схема — одного сдвигового регистра с делением на . Аппаратура проще и работает на потоке битов без ожидания всего блока, поэтому на практике применяют циклическую версию.
Как проверить, что подходит для кода длины ?
Поделить на : остаток должен быть нулевым. Для и деление выходит нацело, значит код (7,4) существует. Если не делит , кодировать можно, но цикличность потеряется — сдвиг кодового слова выйдет из кода.
Почему CRC не исправляет ошибки?
CRC — обнаруживающий код: хвост из 32 проверочных битов при килобайтных кадрах даёт слишком низкую избыточность для локализации. Синдром-остаток имеет значений на кадры из десятков тысяч битов — позиций ошибок несравнимо больше, неоднозначность неизбежна. Исправляющие коды (Рида—Соломона) тратят избыточность щедрее и работают с блоками разумной длины.
Что общего у деления многочленов и алгоритма Евклида?
Всё: тот же столбик, тот же выбор старшего члена, та же гарантия . Многочлены над образуют кольцо с делением с остатком, поэтому к ним применимы НОД, алгоритм Евклида и теория неприводимых делителей — та же структура, что у целых чисел. Именно из неприводимых множителей и собирают порождающие многочлены кодов БЧХ.
Готовитесь к контрольной?
Чеклист тем по «Дискретка»: что вы уже умеете, что повторить и в каком порядке.
Открыть чеклист предмета →
Проверьте себя в бою
Босс-экзамен по «Дискретка»: квизы всех уроков плюс бесконечный поток сгенерированных задач. Каждая попытка — новый расклад.
Начать босс-экзамен →