Контрольные суммы
Хранение данных и их передача часто сопровождается или может сопровождаться
ошибками. Приемнику и передатчику информации необходимо знать, что данные
в потоке должны соответствовать определенным правилам. Приводя реальный
поток в соответствие с этими правилами, приемник может восстановить его
исходное содержание. Количество и типы практически восстановимых ошибок
определяются применяемыми правилами кодирования. Понятно, что всегда существует
(и во многих случаях может быть теоретически оценен) порог количества
ошибок в сообщении, после которого сообщение не поддается даже частичному
восстановлению.
Соответствие потока данных тем или иным правилам теория информации описывает
как наличие статистических автокорреляций или информационной избыточности
в потоке. Такие данные всегда будут иметь больший объем, чем эквивалентные,
но не соответствующие никаким правилам (например, упакованные), т. е.
помехозащищенность достигается не бесплатно. Существование "бесплатных"
средств повышения помехозащищенности каналов противоречит, ни много, ни
мало, Второму Началу термодинамики (доказательство этого утверждения требует
глубоких знаний в области теории информации и термодинамики, и поэтому
здесь не приводится).
Естественные языки обеспечивают очень высокую (в письменной форме Двух-
и трехкратную, а в звуковой еще большую) избыточность за счет применения
сложных фонетических, лексических и синтаксических правил. Остроумным
способом дополнительного повышения избыточности человеческой речи являются
стихи (белые и, тем более, рифмованные), широко использовавшиеся до изобретения
письменности для повышения надежности хранения в человеческих же головах
исторических сведений и священных текстов.
К сожалению, с задачей восстановления искаженных сообщений на естественных
языках в общем случае может справиться лишь человеческий мозг. Правила
кодирования, применимые в вычислительных системах, должны удовлетворять
не только требованиям теоретико-информационной оптимальности, но и быть
достаточно просты для программной или аппаратной реализации.
Простейшим способом внесения избыточности является полное дублирование
данных. Благодаря своей простоте, этот способ иногда применяется ни практике,
но обладает многочисленными недостатками. Во-первых, избыточность этого
метода чрезмерно высока для многих практических применений. Во-вторых,
он позволяет только обнаруживать ошибки, но не исправлять их: при отсутствии
других правил кодирования, мы не можем знать, какая из копий верна, а
какая ошибочна.
Троекратное копирование обеспечивает еще более высокую избыточность, зато
при его использовании для каждого расходящегося бита мы можем проводить
голосование: считать правильным то значение, которое присутствует минимум
в двух копиях данных (в данном случае мы исходим из того, что вероятность
ошибки в одном и том же бите двух копий достаточно мала).
Трехкратное копирование, таким образом, позволяет восстанавливать данные,
но имеет слишком уж высокую избыточность. Эти примеры, кроме простоты,
любопытны -тем, что демонстрируют нам практически важную классификацию
избыточных кодов: бывают коды, которые только обнаруживают ошибки, а бывают
и такие, которые позволяют их восстанавливать. Далеко не всегда коды второго
типа могут быть построены на основе кодов первого типа. Во многих случаях,
например при передаче данных по сети, целесообразно запросить повтор испорченного
пакета, поэтому коды, способные только обнаруживать ошибки, практически
полезны и широко применяются.
Все данные, с которыми могут работать современные вычислительные системы,
представляют собой последовательности битов, поэтому все правила, которые
мы далее будем рассматривать, распространяются только на такие последовател
ьности.
Простейший из применяемых способов кодирования с обнаружением ошибок —
это бит четности. Блок данных снабжается дополнительным
битом, значение которого выбирается так, чтобы общее количество битов,
равных единице, в блоке было четным. Такой код позволяет обнаруживать
ошибки в одном бите блока, но не в двух битах (строго говоря — позволяет
обнаруживать нечетное количество ошибочных битов). Если вероятность ошибки
в двух битах достаточно велика, нам следует либо разбить блок на два блока
меньшего размера, каждый со своим битом четности, либо использовать более
сложные схемы кодирования.
Самая распространенная из таких более сложных схем — это CRC (Cyclic Redundancy
Code, циклический избыточный код). При вычислении CRC разрядности N выбирают
число R требуемой разрядности и вычисляют остаток от деления на R блока
данных (рассматриваемого как единое двоичное число), сдвинутого влево
на N битов. Двоичное число, образованное блоком данных и остатком, делится
на R, и этот факт можно использовать для проверки целостности блока (но
не для восстановления данных при ошибке!).
Способность контрольной суммы обнаруживать ошибки логичнее измерять не
в количестве ошибочных битов, а в вероятности необнаружения ошибки. При
использовании CRC будут проходить незамеченными лишь сочетания ошибок,
удовлетворяющие весьма специальному условию, а именно такие, вектор ошибок
(двоичное число, единичные биты которого соответствуют ошибочным битам
принятого блока, а нулевые — правильно принятым) которых делится на R.
При случайном распределении ошибок вероятность этого может быть грубо
оценена как 1/R, поэтому увеличение разрядности контрольной суммы в сочетании
с выбором простых R обеспечивает достаточно быстрый и дешевый способ проверки
целостности даже довольно длинных блоков. 32- разрядный CRC обеспечивает
практически полную гарантию того, что данные не были повреждены, а 8-разрядный
— уверенность, достаточную для многих целей. Однако ни четность, ни CRC
не могут нам ничем помочь при восстановлении поврежденных данных.
Простой метод кодирования, позволяющий не только обнаруживать, но и исправлять
ошибки, называется блочной или параллельной четностью и состоит в том,
что мы записываем блок данных в виде двухмерной матрицы и подсчитываем
бит четности для каждой строки и каждого столбца. При одиночной ошибке,
таким образом, мы легко можем найти бит, который портит нам жизнь. Двойные
ошибки такая схема кодирования может обнаруживать, но не способна восстанавливать
(рис. 1.9).
Рис. 1.9. Параллельная четность
Широко известный и применяемый код Хэмминга (Hamming
code) находится в близком родстве с параллельной четностью. Его
теоретическое обоснование несколько менее очевидно, чем у предыдущего
алгоритма, но в реализации он, пожалуй, даже проще [Берлекэмп 1971]. Идея
алгоритма состоит в том, чтобы снабдить блок данных несколькими битами
четности, подсчитанными по различным совокупностям битов данных. При выполнении
неравенства Хэмминга (1.1) сформированный таким образом код обеспечивает
обнаружение и исправление одиночных ошибок либо гарантированное обнаружение
(но не исправление!) двойных ошибок. Важно подчеркнуть гарантию обнаружения,
в отличие от всего лишь высокой вероятности обнаружения при использовании
CRC.
d + р+1<= 2р, (1.1)
где d — количество битов данных, р
— разрядность контрольного кода.
Код, использующий d и р,
при которых выражение (1.1) превращается в равенство, называют оптимальным
кодом Хэмминга.
Часто оказывается целесообразно сочетать упаковку данных с их избыточным
кодированием. Наиболее удачным примером такой целесообразности опять-таки
являются тексты на естественных языках: статистический анализ такого текста
показывает очень высокий, более чем двукратный, уровень избыточности.
С одной стороны, это слишком "много для большинства практически применяемых
способов цифровой передачи и кодирования данных, а с другой — правила
формирования этой избыточности слишком сложны и плохо формализованы для
использования в современных программно-аппаратных комплексах. Поэтому
для длительного хранения или передачи по низкоскоростным линиям целесообразно
упаковывать текстовые данные и снабжать их простыми средствами избыточности,
например CRC.
|