Сообщений 0    Оценка 500        Оценить  
Система Orphus

Код Грея

Автор: Холодилов Сергей Александрович
Опубликовано: 23.08.2010
Исправлено: 10.12.2016
Версия текста: 1.1

Разработка
Понятное объяснение
В общем виде
Историческая справка
Генерация последовательности
Кодирование значения
Обоснование равносильности
Соседи
Симметричность
.. и всё же
Декодирование
+1
Чётные
Нечётные
Вместе
+много
Ещё о вычислении значения
Обобщения
n-мерный куб
Применение
Список литературы

Затем мы отправимся, но куда - не скажу; во всяком случае, недалеко отсюда.
Я еду к жене. Она еще не жена мне, но будет ею. Мне нужны алые паруса, чтобы
 еще издали, как условлено с нею, она заметила нас. Вот и все. Как видите, 
здесь нет ничего таинственного. И довольно об этом. 

Александр Грин, «Алые паруса»

Представьте себе, что вы – молодой капитан Грей, уже знающий, что Ассоль сидит на берегу, смотрит вдаль и ждёт. Ушибленный на голову волшебник обещал ей принца, использующего такое двоичное представление чисел, что коды соседних чисел отличаются ровно на один бит.

Чего не сделаешь ради счастья любимой женщины, приходится придумывать. В каких ещё ситуациях такое кодирование может оказаться полезным – посмотрим в конце.

Наложим несколько ограничений:

Кодировку, удовлетворяющую этим ограничениям, назовём вменяемой (это же математика! тут нельзя без строгой терминологии). Очевидное необходимое и достаточное условие вменяемости:

ПРИМЕЧАНИЕ

Т.е. для любого x и любого n, если x < 2n, код x не длиннее n. Длина кода – позиция старшего единичного разряда.

Отсюда сразу получаем:

А вот дальше могут быть варианты. А жаль, а то бы сразу раз – и всё построили.

Разработка

Раз сразу не получилось, попробуем подумать:

Получили следующую схему:

ПРИМЕЧАНИЕ

Вертикальная черта (символ «|») означает конкатенацию строк.

0

00...000000000000

1

00...000000000001

2

00...000000000011

...

...

2n-1

00...000 | код(2n-1)

2n

00...001 | код(2n-1)

в n-том бите появилась 1

2n+1

00...001 | xxxxxxxx

и эта единица передаётся дальше

...

...

...

00...001 | xxxxxxxx

и дальше

...

...

2n+1-1

00...001 | xxxxxxxx

и вплоть до 2n+1-1

2n+1

00...011 | xxxxxxxx

и так она оказывается в 2n+1

2n+1+1

00...01 | xxxxxxxxx

а вот дальше уже не факт

...

...

Теперь предположим, что мы добрались до 2n и надо двигаться дальше – к 2n+1.

Итого: нужно перебрать все комбинации из n битов, так, чтобы первой был код 2n-1, и каждые две соседние отличались бы ровно одним битом.

Вариантов такого перебора много, но среди них есть один красивый. Дело в том, что у нас уже есть подходящая последовательность: коды чисел от 0 до 2n-1. Если взять её в обратном порядке, получится ровно то, что нужно.

Это и есть код Грея.

Понятное объяснение

Начнём с первых двух чисел, закодируем их нулём и единицей:

Ноль       0
Один       1

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

Ноль       0
Один       1
          --  - ось симметрии
           1
           0

Кодов стало больше, и соседи отличаются друг от друга не более чем одним битом. Но есть повторы. Чтобы не было повторов, допишем спереди к первой половине кодов 0, а ко второй 1.

Ноль      00
Один      01
         ---
Два       11
Три       10

Точно так же мы можем отразить и их

Ноль      00
Один      01
Два       11
Три       10
         ---
          10
          11 
          01
          00

И тоже добавим в первую половину 0, а во вторую – 1.

Ноль     000
Один     001
Два      011
Три      010
        ----
Четыре   110
Пять     111
Шесть    101
Семь     100

И т.п.

В общем виде

Должно быть уже понятно, но на всякий случай:

0

00000

1

00001

2

00011

зеркально отражается младший разряд

3

00010

...

...

2n-2

00...000 | gray(2n-2)

2n-1

00...000 | gray(2n-1)

2n

00...001 | gray(2n-1)

очередное отражение

2n+1

00...001 | gray(2n-2)

2n+2

00...001 | gray(2n-3)

...

...

2n+1-2

00...001 | gray(1)

2n+1-1

00...001 | gray(0)

обратите внимание на то, чему равен этот код

2n+1

00...011 | gray(0)

...

...

Историческая справка

Именно в таком виде этот код был предложен инженером Bell Labs Фрэнком Греем (Frank Gray) в 1947-м году. Код описан в патенте 2632058 (оформлен в 1953-м), и подраздел «Понятное объяснение» целиком стянут оттуда (вслед за [Doran 07]). Первоначально Грей предложил название «reflected binary code», но очень быстро на него начали ссылаться просто как на «код Грея».

С предысторией несколько сложнее.

В 1870-x годах французский инженер Эмиль Бодо (Émile Baudot) занимался усовершенствованием телеграфа; в 1878-м году его телеграф получил золотую медаль на Всемирной выставке в Париже, после чего быстро распространился по миру. В то время телеграфы в основном передавали морзянку, основное отличие телеграфа Бодо было в том, что он печатал буквы. Конечно, для этого ему потребовался двоичный код фиксированной длины.

Разрабатывая код, Бодо боролся с нечеловеческим интерфейсом ввода данных. Клавиатура его телеграфа состояла из пяти клавиш, каждая из которых отвечала за один бит, коды символов вводились вручную (и при этом нужно было выдерживать правильный темп!). Бодо стремился минимизировать количество переключений и этим упростить работу оператора.

Скорее всего, он проанализировал частотность биграмм и поместил на «соседние» кодовые позиции часто встречающиеся рядом буквы. Но код Грея даёт только две соседние позиции (следующее и предыдущее слово). А для слова из пяти бит их, конечно, пять, и жалко терять остальные.

Дальше есть два варианта:

Картинки, на которых код Бодо похож на код Грея, выглядят специфически: по горизонтали отложены четыре варианта положения клавиш левой руки, по вертикали – восемь вариантов положения правой, на пересечениях находятся символы. Положения клавиш приведены в порядке кода Грея.

В 1901-м году Дональд Мюррей (Donald Murray) сделал нормальную клавиатуру для телеграфа, и заодно переработал код.

ПРИМЕЧАНИЕ

Основная публикация, связывающая Эмиля Бодо и код Грея, это статья Heath, F. G. "Origin of the Binary Code" (Scientific American vol. 227 no. 2, Aug 1972), в сети она не доступна, но и ничего интересного (не вообще, а по данному вопросу) там нет. Аргументов о том, зачем Бодо потребовался код Грея автор не приводит (точнее, пытается привести, но явно мимо), наоборот, сообщает, что в 1882-м году Бодо переработал кодировку (больше нигде упоминаний об этом не нашёл). Значит, видимо, технических препятствий для этого не было.

Информация об устройстве телеграфа Бодо из статей про телеграф (например: раз, два). Код Грея в них не упоминается.

Генерация последовательности

Действуем по определению. Возрастающая последовательность n-битных кодов строится из последовательности (n-1)-битных следующим образом:

Если читать это в обратном порядке, получится, естественно, убывающая n-битная последовательность. Соответственно, она строится аналогично, изменится только старший разряд:

Реализация:

      # n - ширина в битах
      # d - направление. 0 -- вверх, 1 -- вниз. 
def generate(n, d = 0):
    if n == 0:
        return [[]]
    if d == 0:
        # возрастающая 
        return [[0] + x for x in generate(n-1, 0)] # первая половина
             + [[1] + x for x in generate(n-1, 1)] # вторая половина
    else:
        # убывающая
        return [[1] + x for x in generate(n-1, 0)]
             + [[0] + x for x in generate(n-1, 1)]

Или, то же самое, чуть более изящно (заметим закономерность, связывающую значения d и значения n-ного разряда):

def generate(n, d = 0):
    if n == 0:
        return [[]]
    return [[d]   + x for x in generate(n-1, 0)] 
         + [[1-d] + x for x in generate(n-1, 1)]

На С++:

      // Возвращает value с n-ым битом, установленным в b
      int setBit(int value, int n, int b)
{
    return (value & ~(1 << n)) | (b << n);
}

// [in]  n - количество бит// [in]  d - направление, 0 -- возрастает, 1 -- убывает// [out] result - массив с результатами. Длинна должна быть не меньше чем 2**n// Возвращает: количество сгенерированных чиселint generateGray(int n, int d, int* result)
{
    if (n == 0) return 1;

    // Получаем возрастающую последовательностьint firstHalf = generateGray(n - 1, 0, result);

    for (int i = 0; i < firstHalf; i++)
    {
        // Устанавливает n-й бит (биты нумеруются с 0!) в d
        result[i] = setBit(result[i], n - 1, d);
    }

    // Получаем убывающую последовательностьint secondHalf = generateGray(n - 1, 1, result + firstHalf);

    for (int i = 0; i < secondHalf; i++)
    {
        // Устанавливает n-й бит в (d-1)
        result[firstHalf + i] = setBit(result[firstHalf + i], n - 1, 1 - d);
    }

    return firstHalf + secondHalf;
}

Кодирование значения

Во-первых, это тоже можно сделать по определению. Идея очень простая:

0

0 | gray(0)

1

0 | gray(1)

...

...

2n-2

0 | gray(2n-2)

2n-1

0 | gray(2n-1)

2n

1 | gray(2n-1)

2n+1

1 | gray(2n-1 - 1)

первый шаг вниз по убывающей последовательности

2n+2

1 | gray(2n-1 - 2)

второй

...

...

2 n +x

1 | gray(2n-1 - x)

шаг номер x

...

...

Код:

      # n -- значение
      # b -- разрядность
def encode2Gray1(value, n):
    if n == 0:
        return 0   
    highBit = (1 << (n - 1))
    if value < highBit:
        return encode2Gray1(value, n - 1)
    # столько шагов нужно будет сделать вниз по убывающей последовательности
    rest = value - highBit 
    # А это то же самое, что сделать highBit - 1 - rest шагов по возрастающей
    return highBit + encode2Gray1(highBit - 1 - rest, n - 1)
ПРИМЕЧАНИЕ

Обратите внимание на выражение (highBit – 1 – rest). highBit-1 это двоичное число вида 11..1, состоящее из n-1 единичек. Вычитание из 11..1 это просто операция инвертирования. То есть, при кодировании в код Грея, каждый раз, когда мы получаем 1, мы инвертируем остаток кодируемого числа. На следующем шаге берём его старший бит и так далее.

Но есть другой вариант. Давайте займёмся странными исследованиями и найдём неожиданную закономерность. Исследования следующие: вместе с кодом Грея будем генерировать обычный двоичный код. Ну, просто так, вдруг чего обнаружим.

      # Возвращает список пар, первый элемент пары -- двоичный код, второй -- код Грея
def generateGB(n, d = 0):
    if n == 0:
        return [([], [])]
    
    # Явно выпишем половинки и значения битов на текущем этапе
    bn0 = 0
    gn0 = d
    res0 = generateGB(n-1, 0)

    bn1 = 1    
    gn1 = 1-d
    res1 = generateGB(n-1, 1)
    
    return [ ([bn0] + x, [gn0] + y) for x,y in res0] 
         + [ ([bn1] + x, [gn1] + y) for x,y in res1]

Отметим следующие замечательные факты:

Середину функции можно переписать так:

    ...
    bn0 = 0
    gn0 = d ^ bn0   # т.к. это равно d
    res0 = generateGB(n-1, bn0)

    bn1 = 1    
    gn1 = d ^ bn1   # a это равно 1-d
    res1 = generateGB(n-1, bn1)
    ...

С учётом того, что d это предыдущий (старший) разряд двоичного кода, получаем, что g[i] = b[i+1] ^ b[i]. И очевидную функцию кодирования:

def encode2Gray2(b):
    return b ^ (b >> 1)

Результат не очевидный, есть ощущение, что он получен каким-то трюком, и хорошо ещё, если обошлось без жульничества. Попробуем обосновать.

Обоснование равносильности

Способ вычисления кода Грея g = b ^ (b >> 1) со всех сторон замечателен, но пока непонятно, почему у соседей будет отличаться только один бит, и почему вся эта конструкция будет симметрична, т.е. похожа на наш, "всамделишный" код Грея.

Соседи

Пусть b = b[n] .. b[k] | 01..1

ПРИМЕЧАНИЕ

Последовательность единиц или последовательность b[n]-b[k] может быть пустой, это ни на что не повлияет.

Тогда b+1 = b[n] .. b[k] | 10..0. Запишем в столбик.

g0 = b ^ (b >> 1):

b:

B[n]

b[n-1]

b[k]

0

1

1

...

1

b >> 1:

0

b[n]

b[k+1]

b[k]

0

1

...

1

g0:

b[n] ^ 0

b[n-1] ^ b[n]

b[k] ^ b[k+1]

0 ^ b[k]

1 ^ 0

1^1

...

1^1

g1 = (b+1) ^ ((b+1) >> 1):

b+1:

b[n]

b[n-1]

b[k]

1

0

0

...

0

(b+1) >> 1:

0

b[n]

b[k+1]

b[k]

1

0

...

0

g1:

b[n] ^ 0

b[n-1] ^ b[n]

b[k] ^ b[k+1]

1 ^ b[k]

0 ^ 1

0^0

...

0^0

Видно, что изменился ровно один разряд. И даже видно, какой именно – запомните, дальше пригодится.

Симметричность

По построению кода Грея, должно выполняться равенство gray(2n + x) = 1 | gray(2n - 1 - x). Проверим.

g0 = (2n + x) ^ ((2n + x) >> 1):

2n + x:

1

x[n-1]

x[n-2]

x[0]

(2n + x) >> 1:

0

1

x[n-1]

x[1]

g0:

1 ^ 0

x[n-1] ^ 1

x[n-2] ^ x[n-1]

x[0] ^ x[1]

С учётом того, что 2n – 1 – x это инвертированное x, g1 = (2n - 1 - x) ^ ((2n - 1 - x) >> 1):

2n – 1 – x :

0

!x[n-1]

!x[n-2]

!x[0]

(2n – 1 – x) >> 1:

0

0

!x[n-1]

!x[1]

g1:

0 ^ 0

!x[n-1] ^ 0

!x[n-2] ^ !x[n-1]

!x[0] ^ !x[1]

Сравниваем:

Что и требовалось доказать.

.. и всё же

Доказать доказали, но понятнее, почему это одно и тоже от этого не стало.

Равенство g[i] = b[i+1] ^ b[i] равносильно равенству g[i] = (b[i+1] != b[i]). То есть, в коде Грея единичка будет в том месте, где в обычном двоичном коде был переход 0-1 или 1-0 (включая первый переход, из 0 в старший единичный разряд). Например, так:


Рис. 1. Преобразование из обычного двоичного кода в код Грея

А теперь помедитируйте над абзацем, описывающим работу функции encode2Gray1:

То есть, при кодировании в код Грея, каждый раз, когда мы получаем 1, мы инвертируем остаток кодируемого числа. На следующем шаге берём его старший бит и так далее.

.. и осознайте, что это в точности то же самое.

Таким образом, взаимосвязь между двумя способами кодирования будем считать прояснённой. Это не случайность и не трюк.

Декодирование

Тоже можно сделать по определению, и тоже понятно как:

Код:

def decodeFromGray1(value, n):
    if n == 0:
        return 0
    highBit = (1 << (n - 1))
    if value < highBit:
        return decodeFromGray1(value, n - 1)
    return highBit + (highBit - 1 - decodeFromGray1(value - highBit, n - 1))
ПРИМЕЧАНИЕ

Аналогично функции кодирования, выражение (highBit - 1 - decodeFromGray1(n - highBit, b - 1)) это инвертирование, только теперь уже результата декодирования остатка (что логично).

Другой вариант декодирования получается из g[i] = b[i+1] ^ b[i]. Из него сразу же следует b[i] = g[i] ^ b[i+1]. Ну и:

      
b[n] = 0 b[n-1] = g[n-1] ^ b[n] = g[n-1] b[n-2] = g[n-2] ^ b[n-1] = g[n-2] ^ g[n-1] b[n-3] = g[n-3] ^ b[n-2] = g[n-3] ^ g[n-2] ^ g[n-1] ... b[n-i] = g[n-i] ^ g[n-i+1] ^ ... ^ g[n-1] ...
ПРИМЕЧАНИЕ

Если g[i] равен 1, он инвертирует все равенства, в которых участвует, т.е. инвертирует значения битов b[i]-b[0]. Это как раз тот самый "остаток".

А реализовать это проще всего так:

def decodeFromGray2(value, n):
    res = value
    for i in range(1, n):
        res ^= (value >> i)
    return res
ПРИМЕЧАНИЕ

Реализацию можно ускорить, если заметить, что выражение:

y = x ^ (x >> 1) ^ (x >> 2) ^ (x >> 3)

можно вычислить так

x1 = x ^ (x >> 1)

y = x1 ^ (x1 >> 2)

+1

Задача получить следующий элемент кода, имея текущий, приходит в голову сразу. Пока что было два варианта решения: либо сгенерировать сразу серию, либо перекодировать в двоичный код, прибавить в единицу, и перекодировать обратно в код Грея. Оба варианта не очень красивые. Попробуем придумать алгоритм для честного прибавления единицы в коде Грея.

Из того, что в коде Грея единицы соответствуют переключениям 0-1 и 1-0 в обычном двоичном коде, получаем, что пары единиц кода Грея задают диапазоны единиц в двоичном коде.


Рис. 2. Преобразование из кода Грея в двоичный.

Что сразу видно:

Посмотрим, что будет, если прибавить 1.

Чётные

Итак, младший разряд двоичного кода – 0, и после прибавления единицы он должен стать 1. Но всё равно есть два случая: эта единица может быть отдельно стоящей или она вольётся в ряд таких же единиц.

Обе ситуации изображены на рисунках 3 и 4. В верхней строчке – двоичный код, в нижней – код Грея, единички в коде Грея соответствуют переходам 0-1 и 1-0 в двоичном коде. Изменяющийся бит подчёркнут.


Рис.3. Прибавление 1 к четному числу, версия 1


Рис.4. Прибавление 1 к четному числу, версия 2

Видно, что в обоих случаях для получения кода Грея числа, большего на 1, нужно просто инвертировать младший бит.

Нечётные

Тоже два случая, по тому же признаку: будет новая единица в отдельной группе, или присоединится к какой-то из существующих.


Рис.5. Прибавление 1 к нечётному числу, версия 1.


Рис.6. Прибавление 1 к нечётному числу, версия 2.

И в том и в другом случае нужно инвертировать бит, следующий за первой единицей.

Вместе

Реализация очевидна

        # Самая простая реализация проверки на чётность количества единичных битов
def isGrayEven(n):
    count = 0
    while n:
        if n & 1: count += 1
        n >>= 1
    return (count % 2 == 0)

# Возвращает число, в котором в 1 установлен только один бит,# тот самый, который был младшим единичным в n 
def getLesserOne(n):
    return n & ~(n-1) # почему это работает как надо? :)# Возвращает код Грея, следующий за n
def getNextGray(n):
    if isGrayEven(n):
        return n ^ 1
    return n ^ (getLesserOne(n) << 1)

Если немного подумать, можно написать функцию getPrevGray.

СОВЕТ

Подумайте :)

ПРИМЕЧАНИЕ

И ещё одну деталь можно заметить: в коде Грея инвертируется тот же бит, который переключается с 0 в 1 в двоичном коде.

+много

Сложение чисел в коде Грея по возможной области применимости резко выделяется на фоне остальной части статьи: это уже не просто никому не нужно, это вообще никому не нужно. У самого кода Грея всё же есть разумные применения, но ни одно из известных мне не предполагает суммирования кодовых комбинаций. Но человеческий разум не знает преград.

Пусть A, B, S – слагаемые и сумма в бинарном коде, а Ag, Bg, Sg – в коде Грея.

Идея алгоритма:

Осталось красиво выразить C[i] ^ C[i-1]. Обозначим это выражение за Cg[i] и через пару строчек выкладок получим, что Cg[i] = (A[i] ^ C[i-1]) & (B[i] ^ C[i-1]). Теперь нужно вспомнить, что

То есть Cg[i] это конъюнкция двух выражений, которые несложно вычислять рекурсивно на каждом шаге. Ну и нужно как-то начать, и это тоже несложно. Итого, шаг алгоритма:

Где E[i] и F[i] это части Cg[i].

ПРИМЕЧАНИЕ

Этот алгоритм без пояснений и обоснований приведён в [Doran 07], понять его в таком виде не просто: мне не удалось. Два различных объяснения алгоритма есть в [Lucal 59], одно из них (менее красивое, зато более формальное) я кратко привёл выше. Там же описан алгоритм вычитания, но это уж слишком.

Ещё о вычислении значения

Посмотрим, что такое «диапазоны единиц».

Итоговое значение это просто сумма всех получившихся «полос». То есть, если t1,..tm – номера битов, равных 1 в коде Грея, и t1 < t2 < .. < tm, то при преобразовании в двоичный код мы получим:

(2t[m]+1-1) – (2t[m-1]+1-1) + (2t[m-2]+1-1) – (2t[m-3]+1-1) + … + (2t[2]+1-1) – (2t[1]+1-1)

если m – чётное и

(2t[m]+1-1) – (2t[m-1]+1-1) + (2t[m-2]+1-1) – (2t[m-3]+1-1) + … + (2t[3]+1-1) – (2t[2]+1-1) + (2t[1]+1-1)

в противном случае.

Пусть P(a1..ak) равно 0, если среди битов a1..ak чётное количество единичных и 1, если их нечётное. Тогда оба эти выражения можно свести в одно. Следующая последовательность преобразований:

Приводит к:


То есть, по существу от обычной позиционной системы счисления результат отличается только множителем (-1)P(g[n-1]..g[i+1]), из-за которого значение разряда не постоянно, а зависит от количества старших единичных разрядов.

Обобщения

Кодом Грея «в широком смысле» называют любой код, в котором соседние значения отличаются только в одном разряде, а значения этого разряда отличаются на 1.

Есть два разумных направления для обобщений:

По первому вопросу сказать толком нечего. По второму, в общем, тоже. У обобщенного понятия остаётся слишком мало интересных свойств, а разбор конкретных воплощений – дело отдельных статей. Но общий подход ко всем таким кодам стоит упомянуть.

n-мерный куб

n-битное число можно рассматривать как вектор в n-мерном пространстве, каждый бит – координата по соответствующей оси. Все точки с координатами из нулей и единиц это вершины единичного n-мерного кубика, стоящего в начале координат. И все его вершины – это как раз такие точки. У двух соседних вершин отличается ровно одна из координат – по соединяющему их ребру.

Значит, если мы построим путь по рёбрам такого куба, мы получим код, в котором соседние значения отличаются не более чем на один бит. И наоборот, каждому такому коду соответствует путь в n-мерном кубе.

В теории графов путь, проходящий по одному разу через каждую вершину графа, называют Гамильтоновым путём. А если в конце он возвращается в исходную вершину, то это Гамильтонов цикл. Гамильтонову циклу соответствует код, который можно замкнуть и правило «не более одного бита» не нарушиться; т.е. последний элемент отличается от первого на один бит. Такой код называется циклическим. Несложно заметить, что классический код Грея – циклический.

ПРИМЕЧАНИЕ

Вершинами n-мерного куба представляют самые разные двоичные коды, не только коды Грея. Такова традиция.

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

Применение

Патент Фрэнка Грея посвящён преобразователю аналогового сигнала в цифровой. Преобразователь устроен следующим образом:


Рис.7. Преобразователь, описанные части схемы выделены красным, луч электронов зелёным (картинка взята из [Gray 53]).

Это все придумал не Грей, это было до него. Грей придумал, как победить основную проблему этого преобразователя: если луч оказывается около границы двух строк, до анода доходит случайная смесь из первой и второй строки. Так как в обычном двоичном коде соседние строки могут отличаться довольно сильно, погрешность получается большой. Идея Грея была в том, что если строки отличаются только одним битом, то, как ни смешивай, дойдёт либо одна, либо вторая.

Та же мысль применяется, например, в датчиках угла поворота.


Рис.8. Круговой энкодер с трёхбитным кодом Грея (картинка взята из википедии, спасибо им)

Но здесь оказывается важным ещё и то, что разница между первым и последним кодом тоже 1 бит, т.е. то, что код Грея циклический.

В других областях коды Грея могут использоваться, если нужно перебрать все варианты чего-либо, и то, что соседние варианты отличаются мало, позволяет сократить вычисления (использовать результаты вычислений над предыдущим вариантом, чуть-чуть изменив их, а не вычислять всё заново). В [Guan 96] этот подход использован для подбора коэффициентов полинома кода коррекции ошибок. Автор утверждает, что помогло.

ПРИМЕЧАНИЕ

Если вы не поняли предпоследнее предложение – не отчаивайтесь, это абсолютно не важно. Я тоже не вполне его понимаю.

Список литературы


Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав.
    Сообщений 0    Оценка 500        Оценить