что такое код хемминга
Избыточное кодирование, код Хэмминга
Избыточное кодирование (англ. redundant encoding) — вид кодирования, использующий избыточное количество информации с целью последующего контроля целостности данных при записи/воспроизведении информации или при её передаче по линиям связи.
Определение: |
Код определяет [math]d[/math] ошибок, если при передаче кодового слова, в котором [math]\leq d[/math] ошибок, алгоритм декодирования скажет, что есть ошибка. |
Определение: |
Код исправляет [math]d[/math] ошибок, если при передаче кодового слова, в котором [math]\leq d[/math] ошибок, алгоритм декодирования сможет восстановить исходное слово. |
Содержание
Код, определяющий одну ошибку [ править ]
Кодирование Хэмминга [ править ]
[math]a[/math] | [math]b[/math] | [math]a \oplus b[/math] |
---|---|---|
[math]c[/math] | [math]d[/math] | [math]c \oplus d[/math] |
[math]a \oplus c[/math] | [math] b \oplus d [/math] |
По аналогичному принципу можно закодировать любое число бит. Пусть мы имеем исходную строку длиной в [math]2^k[/math] бит. Для получения её кода добавим к ней [math]k[/math] пар бит по следующему принципу:
Теперь заметим, что в случае наличия ошибки в исходной строке, ровно один бит в каждой паре будет равен единице. Тогда можно оставить только один бит из пары. Однако этого будет недостаточно, поскольку если только один добавленный бит не соответствует строке, то нельзя понять, ошибка в нём или в строке. На этот случай можно добавить ещё один контрольный бит — [math] \mathrm X \mathrm O \mathrm R[/math] всех битов строки.
Определение и устранение ошибок в общем случае [ править ]
Пусть [math]\Sigma[/math] — исходный алфавит, [math]C: \Sigma \to B^m[/math] — кодирование, [math]B=(0,1)[/math]
[math]d: B^m \times B^m \to \mathbb
Определим [math]d_0 = \min[/math] [math]
Тогда легко понять, что код, полученный преобразованием [math]C[/math] может исправлять [math]
Код Хэмминга. Пример работы алгоритма
Прежде всего стоит сказать, что такое Код Хэмминга и для чего он, собственно, нужен. На Википедии даётся следующее определение:
Коды Хэмминга — наиболее известные и, вероятно, первые из самоконтролирующихся и самокорректирующихся кодов. Построены они применительно к двоичной системе счисления.
Другими словами, это алгоритм, который позволяет закодировать какое-либо информационное сообщение определённым образом и после передачи (например по сети) определить появилась ли какая-то ошибка в этом сообщении (к примеру из-за помех) и, при возможности, восстановить это сообщение. Сегодня, я опишу самый простой алгоритм Хемминга, который может исправлять лишь одну ошибку.
Также стоит отметить, что существуют более совершенные модификации данного алгоритма, которые позволяют обнаруживать (и если возможно исправлять) большее количество ошибок.
Сразу стоит сказать, что Код Хэмминга состоит из двух частей. Первая часть кодирует исходное сообщение, вставляя в него в определённых местах контрольные биты (вычисленные особым образом). Вторая часть получает входящее сообщение и заново вычисляет контрольные биты (по тому же алгоритму, что и первая часть). Если все вновь вычисленные контрольные биты совпадают с полученными, то сообщение получено без ошибок. В противном случае, выводится сообщение об ошибке и при возможности ошибка исправляется.
Как это работает.
Для того, чтобы понять работу данного алгоритма, рассмотрим пример.
Подготовка
Допустим, у нас есть сообщение «habr», которое необходимо передать без ошибок. Для этого сначала нужно наше сообщение закодировать при помощи Кода Хэмминга. Нам необходимо представить его в бинарном виде.
На этом этапе стоит определиться с, так называемой, длиной информационного слова, то есть длиной строки из нулей и единиц, которые мы будем кодировать. Допустим, у нас длина слова будет равна 16. Таким образом, нам необходимо разделить наше исходное сообщение («habr») на блоки по 16 бит, которые мы будем потом кодировать отдельно друг от друга. Так как один символ занимает в памяти 8 бит, то в одно кодируемое слово помещается ровно два ASCII символа. Итак, мы получили две бинарные строки по 16 бит:
и
После этого процесс кодирования распараллеливается, и две части сообщения («ha» и «br») кодируются независимо друг от друга. Рассмотрим, как это делается на примере первой части.
Прежде всего, необходимо вставить контрольные биты. Они вставляются в строго определённых местах — это позиции с номерами, равными степеням двойки. В нашем случае (при длине информационного слова в 16 бит) это будут позиции 1, 2, 4, 8, 16. Соответственно, у нас получилось 5 контрольных бит (выделены красным цветом):
Было:
Стало:
Таким образом, длина всего сообщения увеличилась на 5 бит. До вычисления самих контрольных бит, мы присвоили им значение «0».
Вычисление контрольных бит.
Теперь необходимо вычислить значение каждого контрольного бита. Значение каждого контрольного бита зависит от значений информационных бит (как неожиданно), но не от всех, а только от тех, которые этот контрольных бит контролирует. Для того, чтобы понять, за какие биты отвечает каждых контрольный бит необходимо понять очень простую закономерность: контрольный бит с номером N контролирует все последующие N бит через каждые N бит, начиная с позиции N. Не очень понятно, но по картинке, думаю, станет яснее:
Здесь знаком «X» обозначены те биты, которые контролирует контрольный бит, номер которого справа. То есть, к примеру, бит номер 12 контролируется битами с номерами 4 и 8. Ясно, что чтобы узнать какими битами контролируется бит с номером N надо просто разложить N по степеням двойки.
Но как же вычислить значение каждого контрольного бита? Делается это очень просто: берём каждый контрольный бит и смотрим сколько среди контролируемых им битов единиц, получаем некоторое целое число и, если оно чётное, то ставим ноль, в противном случае ставим единицу. Вот и всё! Можно конечно и наоборот, если число чётное, то ставим единицу, в противном случае, ставим 0. Главное, чтобы в «кодирующей» и «декодирующей» частях алгоритм был одинаков. (Мы будем применять первый вариант).
Высчитав контрольные биты для нашего информационного слова получаем следующее:
и для второй части:
Вот и всё! Первая часть алгоритма завершена.
Декодирование и исправление ошибок.
Теперь, допустим, мы получили закодированное первой частью алгоритма сообщение, но оно пришло к нас с ошибкой. К примеру мы получили такое (11-ый бит передался неправильно):
Вся вторая часть алгоритма заключается в том, что необходимо заново вычислить все контрольные биты (так же как и в первой части) и сравнить их с контрольными битами, которые мы получили. Так, посчитав контрольные биты с неправильным 11-ым битом мы получим такую картину:
Как мы видим, контрольные биты под номерами: 1, 2, 8 не совпадают с такими же контрольными битами, которые мы получили. Теперь просто сложив номера позиций неправильных контрольных бит (1 + 2 + 8 = 11) мы получаем позицию ошибочного бита. Теперь просто инвертировав его и отбросив контрольные биты, мы получим исходное сообщение в первозданном виде! Абсолютно аналогично поступаем со второй частью сообщения.
Заключение.
В данном примере, я взял длину информационного сообщения именно 16 бит, так как мне кажется, что она наиболее оптимальная для рассмотрения примера (не слишком длинная и не слишком короткая), но конечно же длину можно взять любую. Только стоит учитывать, что в данной простой версии алгоритма на одно информационное слово можно исправить только одну ошибку.
Примечание.
На написание этого топика меня подвигло то, что в поиске я не нашёл на Хабре статей на эту тему (чему я был крайне удивлён). Поэтому я решил отчасти исправить эту ситуацию и максимально подробно показать как этот алгоритм работает. Я намеренно не приводил ни одной формулы, дабы попытаться своими словами донести процесс работы алгоритма на примере.
Код Хемминга
Код Хемминга
Коды Хемминга — наиболее известные и, вероятно, первые из самоконтролирующихся и самокорректирующихся кодов. Построены они применительно к двоичной системе счисления.
Содержание
История
В середине 40-х годов Ричард Хемминг работал в знаменитых Лабораториях Белла на счётной машине Bell Model V. Это была электромеханическая машина, использующая релейные блоки,скорость которых была очень низка: один оборот за несколько секунд. Данные вводились в машине с помощью перфокарт, и поэтому в процессе чтения часто происходили ошибки. В рабочие дни использовались специальные коды, чтобы обнаруживать и исправлять найденные ошибки, при этом оператор узнавал об ошибке по свечению лампочек, исправлял и запускал машину. В выходные дни, когда не было операторов, при возникновении ошибки машина автоматически выходила из программы и запускала другую.
Хемминг часто работал в выходные дни, и все больше и больше раздражался, потому что часто был должен перегружать свою программу из-за ненадежности перфокарт. На протяжении нескольких лет он проводил много времени над построением эффективных алгоритмов исправления ошибок. В 1950 году он опубликовал способ, который на сегодняшний день мы знаем как код Хемминга.
Самоконтролирующиеся коды
Коды Хемминга являются самоконтролирующимися кодами, т.е кодами, позволяющими автоматически обнаруживать наиболее вероятные ошибки при передаче данных. Для их построения достаточно приписать к каждому слову один добавочный (контрольный) двоичный разряд и выбрать цифру этого разряда так, чтобы общее количество единиц в изображении любого числа было, например, четным. Одиночная ошибка в каком-либо разряде передаваемого слова (в том числе, может быть, и в контрольном разряде) изменит четность общего количества единиц. Счетчики по модулю 2, подсчитывающие количество единиц, которые содержатся среди двоичных цифр числа, могут давать сигнал о наличии ошибок.
При этом, разумеется, мы не получаем никаких указаний о том, в каком именно разряде произошла ошибка, и, следовательно, не имеем возможности исправить её. Остаются незамеченными также ошибки, возникающие одновременно в двух, в четырёх или вообще в четном количестве разрядов. Впрочем, двойные, а тем более четырёхкратные ошибки полагаются маловероятными.
Самокорректирующиеся коды
Диапазон m | kmin |
---|---|
1 | 2 |
2-4 | 3 |
5-11 | 4 |
12-26 | 5 |
27-57 | 6 |
Имея m+k разрядов, самокорректирующийся код можно построить следующим образом.
Среди m+k разрядов кода при этом имеется k разрядов, каждый из которых принадлежит только к одной контрольной группе:
Разряд № 1: 110 = …0000012 принадлежит только к 1-й контрольной группе.
Разряд № 2: 210 = …0000102 принадлежит только к 2-й контрольной группе.
Разряд № 4: 410 = …0001002 принадлежит только к 3-й контрольной группе.
Эти k разрядов мы и будем считать контрольными. Остальные m разрядов, каждый из которых принадлежит, по меньшей мере, к двум контрольным группам, будут информационными разрядами.
В каждой из k контрольных групп будем иметь по одному контрольному разряду. В каждый из контрольных разрядов поместим такую цифру (0 или 1), чтобы общее количество единиц в его контрольной группе было четным.
Например, довольно распространен код Хеминга с m=7 и k=4.
№ разряда: | 0001 | 0010 | 0011 | 0100 | 0101 | 0110 | 0111 | 1000 | 1001 | 1010 | 1011 |
---|---|---|---|---|---|---|---|---|---|---|---|
Распределение контрольных и информационных разрядов | p1 | p2 | d1 | p3 | d2 | d3 | d4 | p4 | d5 | d6 | d7 |
Информационное кодовое слово : | 0 | 1 | 1 | 0 | 1 | 0 | 1 | ||||
p1 | 1 | 0 | 1 | 0 | 1 | 1 | |||||
p2 | 0 | 0 | 1 | 0 | 0 | 1 | |||||
p3 | 0 | 1 | 1 | 0 | |||||||
p4 | 0 | 1 | 0 | 1 | |||||||
Кодовое слово с контрольными разрядами: | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 1 |
Интересно посмотреть, как перекрываются контрольные группы в данном случае (Рис №1). Первая группа контролирует разряды № 3,7,5 исходного кода, вторая — 3,7,6… (№ группы = № контрольного разряда). Очевидно, что они частично перекрываются.
№ разряда: | 0001 | 0010 | 0011 | 0100 | 0101 | 0110 | 0111 | 1000 | 1001 | 1010 | 1011 | ||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Распределение контрольных и информационных разрядов | p1 | p2 | d1 | p3 | d2 | d3 | d4 | p4 | d5 | d6 | d7 | Контроль по четности в группе | Контрольный бит |
Переданное кодовое слово: | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 1 | ||
Принятое кодовое слово: | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 0 | ||
p1 | 1 | 0 | 1 | 0 | 1 | 0 | Fail | 1 | |||||
p2 | 0 | 0 | 1 | 0 | 0 | 0 | Fail | 1 | |||||
p3 | 0 | 1 | 1 | 0 | Pass | 0 | |||||||
p4 | 0 | 1 | 0 | 0 | Fail | 1 |
p4 | p3 | p2 | p1 | |
---|---|---|---|---|
В двоичном представлении | 1 | 0 | 1 | 1 |
В десятичном представлении | 8 | 2 | 1 | Σ = 11 |
Из таблицы следует, что ошибка произошла в 11-м разряде и её можно исправить. Построенный код, разумеется, не рассчитан на возможность одновременной ошибки в двух разрядах.
Например (Рис №2), когда ошибки одновременно прошли в 3-м и 7-м разрядах исходного кода, первый и второй контрольные биты даже не замечают подмены.
Когда в принятом коде производится проверка четности внутри контрольных групп, случай двойной ошибки ничем внешне не отличается от случая одиночной ошибки.
Например, предположим теперь, что при передаче данного кодового слова 10001100101 произошли ошибки в 3-м и 6-м разрядах, так, что принято кодовое слово 10101000101.
№ разряда: | 0001 | 0010 | 0011 | 0100 | 0101 | 0110 | 0111 | 1000 | 1001 | 1010 | 1011 | ||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Распределение контрольных и информационных разрядов | p1 | p2 | d1 | p3 | d2 | d3 | d4 | p4 | d5 | d6 | d7 | Контроль по четности в группе | Контрольный бит |
Переданное кодовое слово: | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 1 | ||
Принятое кодовое слово: | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 1 | ||
p1 | 1 | 1 | 1 | 0 | 1 | 1 | Fail | 1 | |||||
p2 | 0 | 1 | 0 | 0 | 0 | 1 | Pass | 0 | |||||
p3 | 0 | 1 | 0 | 0 | Fail | 1 | |||||||
p4 | 0 | 1 | 0 | 1 | Pass | 0 |
p4 | p3 | p2 | p1 | |
---|---|---|---|---|
В двоичном представлении | 0 | 1 | 0 | 1 |
В десятичном представлении | 4 | 1 | Σ = 5 |
Вывод: ошибка произошла в 5-м разряде Истинное кодовое слово : 1 0 0 0 1 1 0 0 1 0 1 Ошибочное кодовое слово : 1 0 1 0 1 0 0 0 1 0 1 Исправленное кодовое слово : 1 0 1 0 0 0 0 0 1 0 1 Результат получается ещё более отдаленным от правильного, чем принятый код. Исправление кода по общему правилу не только не улучшило, но даже ухудшило бы дело.
Код Хемминга
Можно построить и такой код, который обнаруживал бы двойные ошибки и исправлял одиночные. Для этого к самокорректирующемуся коду, рассчитанному на исправление одиночных ошибок, нужно приписать ещё один контрольный разряд (разряд двойного контроля). Полное количество разрядов кода при этом будет m+k+1. Цифра в разряде двойного контроля устанавливается такой, чтобы общее количество единиц во всех m + k + 1 разрядах кода было четным. Этот разряд не включается в общую нумерацию и не входит ни в одну контрольную группу.
№ разряда: | 0001 | 0010 | 0011 | 0100 | 0101 | 0110 | 0111 | 1000 | 1001 | 1010 | 1011 | Second Parity |
---|---|---|---|---|---|---|---|---|---|---|---|---|
Распределение контрольных и информационных разрядов | p1 | p2 | d1 | p3 | d2 | d3 | d4 | p4 | d5 | d6 | d7 | |
Информационное кодовое слово: | 0 | 1 | 1 | 0 | 1 | 0 | 1 | |||||
p1 | 1 | 0 | 1 | 0 | 1 | 1 | ||||||
p2 | 0 | 0 | 1 | 0 | 0 | 1 | ||||||
p3 | 0 | 1 | 1 | 0 | ||||||||
p4 | 0 | 1 | 0 | 1 | ||||||||
Кодовое слово с контрольными разрядами: | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 1 | 1 |
При этом могут быть следующие случаи.
1. В принятом коде в целом и по всем контрольным группам количество единиц четно. Если тройные ошибки и ошибки в большем количестве разрядов исключаются, то первый случай соответствует безошибочному приему кода. Например
№ разряда: | 0001 | 0010 | 0011 | 0100 | 0101 | 0110 | 0111 | 1000 | 1001 | 1010 | 1011 | Контроль по четности в группе | Контрольный бит | Контроль по четности в целом | Контрольный бит в целом |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Распределение контрольных и информационных разрядов | p1 | p2 | d1 | p3 | d2 | d3 | d4 | p4 | d5 | d6 | d7 | ||||
Переданное кодовое слово: | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 1 | ||||
Принятое кодовое слово: | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 1 | ||||
p1 | 1 | 0 | 1 | 0 | 1 | 1 | Pass | 0 | |||||||
p2 | 0 | 0 | 1 | 0 | 0 | 1 | Pass | 0 | |||||||
p3 | 0 | 1 | 1 | 0 | Pass | 0 | |||||||||
p4 | 0 | 1 | 0 | 1 | Pass | 0 | 1 | Pass |
p4 | p3 | p2 | p1 | |
---|---|---|---|---|
В двоичном представлении | 0 | 0 | 0 | 0 |
В десятичном представлении | Σ = 0 |
№ разряда: | 0001 | 0010 | 0011 | 0100 | 0101 | 0110 | 0111 | 1000 | 1001 | 1010 | 1011 | Контроль по четности в группе | Контрольный бит | Контроль по четности в целом | Контрольный бит в целом |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Распределение контрольных и информационных разрядов | p1 | p2 | d1 | p3 | d2 | d3 | d4 | p4 | d5 | d6 | d7 | ||||
Переданное кодовое слово: | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 1 | ||||
Принятое кодовое слово: | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 1 | ||||
p1 | 1 | 0 | 1 | 0 | 1 | 1 | Pass | 0 | |||||||
p2 | 0 | 0 | 1 | 0 | 0 | 1 | Pass | 0 | |||||||
p3 | 0 | 1 | 1 | 0 | Pass | 0 | |||||||||
p4 | 0 | 1 | 0 | 1 | Pass | 0 | 0 | Fail |
p4 | p3 | p2 | p1 | |
---|---|---|---|---|
В двоичном представлении | 0 | 0 | 0 | 0 |
В десятичном представлении | Σ = 0 |
3. В принятом коде в целом и в некоторых из контрольных групп количество единиц нечетно. Третий случай — одиночной ошибки в каком-либо из остальных разрядов (можно исправить в соответствии с приведенными выше правилами)
№ разряда: | 0001 | 0010 | 0011 | 0100 | 0101 | 0110 | 0111 | 1000 | 1001 | 1010 | 1011 | Контроль по четности в группе | Контрольный бит | Контроль по четности в целом | Контрольный бит в целом |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Распределение контрольных и информационных разрядов | p1 | p2 | d1 | p3 | d2 | d3 | d4 | p4 | d5 | d6 | d7 | ||||
Переданное кодовое слово : | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 1 | ||||
Принятое кодовое слово: | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 0 | ||||
p1 | 1 | 0 | 1 | 0 | 1 | 0 | Fail | 1 | |||||||
p2 | 0 | 0 | 1 | 0 | 0 | 0 | Fail | 1 | |||||||
p3 | 0 | 1 | 1 | 0 | Pass | 0 | |||||||||
p4 | 0 | 1 | 0 | 0 | Fail | 1 | 1 | Fail |
p4 | p3 | p2 | p1 | |
---|---|---|---|---|
В двоичном представлении | 1 | 0 | 1 | 1 |
В десятичном представлении | 8 | 2 | 1 | Σ = 11 |
Из таблицы следует, что ошибка произошла в 11-м разряде и что её можно исправить.
№ разряда: | 0001 | 0010 | 0011 | 0100 | 0101 | 0110 | 0111 | 1000 | 1001 | 1010 | 1011 | Контроль по четности в группе | Контрольный бит | Контроль по четности в целом | Контрольный бит в целом |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Распределение контрольных и информационных разрядов | p1 | p2 | d1 | p3 | d2 | d3 | d4 | p4 | d5 | d6 | d7 | ||||
Переданное кодовое слово: | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 1 | ||||
Принятое кодовое слово: | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 1 | ||||
p1 | 1 | 1 | 1 | 0 | 1 | 1 | Fail | 1 | |||||||
p2 | 0 | 1 | 0 | 0 | 0 | 1 | Pass | 0 | |||||||
p3 | 0 | 1 | 0 | 0 | Fail | 1 | |||||||||
p4 | 0 | 1 | 0 | 1 | Pass | 0 | 1 | Pass |
p4 | p3 | p2 | p1 | |
---|---|---|---|---|
В двоичном представлении | 0 | 1 | 0 | 1 |
В десятичном представлении | 4 | 2 | 1 | Σ = 5 |
Раз получившаяся сумма не равна нулю, а контрольный бит указывает на ошибку передачи, то обнаруживаем двойную ошибку. Исправление двойных ошибок здесь, конечно, невозможно.
Увеличивая дальше количество контрольных разрядов, можно было бы построить коды, рассчитанные на исправление двойных ошибок и обнаружение тройных и т.д. Однако методы построения этих кодов не вполне разработаны.
Применение
Код Хэмминга используется в некоторых прикладных программах в области хранения данных, особенно в RAID 2; кроме того, метод Хемминга давно применяется в памяти типа ECC и позволяет «на лету» исправлять однократные и обнаруживать двукратные ошибки.