2016-02-29 21 views
0

Что означает «последовательный серый код»? Я имею в виду, что 10 и 11 являются последовательными в десятичной системе, но что означает «последовательный серый код»? Я знаю только, что серый код - это двоичная система цифр, где два последовательных значения отличаются только одним битом.Если заданы два шестнадцатеричных числа, если они могут быть последовательными в сером коде

Вот решение в Интернете, но я не могу понять это

private static int graycode(byte term1, byte term2) { 
    byte x = (byte)(term1^term2); // why use XOR? 
    int count = 0; 
    while(x!=0) 
    { 
    x = (byte)(x &(x-1)); // why use bitwise operator? 
    count++;    // what is count? 
    } 
    return count == 1; 
} 

Я пытаюсь понять, потратив час, но я до сих пор не имею понятия.

+0

Возможный дубликат [Как найти, если два числа последовательных чисел в серой кодовой последовательности] (HTTP: // StackOverflow .com/questions/27218894/how-to-find-if-two-numbers-are-sequence-numbers-in-gray-code-sequence) – Morwenn

+1

N что два соседа в коде Grey отличаются только одним битом (это то, что выполняет ваша функция), но два числа, отличающиеся только битом, не всегда являются соседями в коде Grey: коды Grey 1000 и 1010 отличаются только одним битом, но не являются соседями (1000 и 1010 соответственно равны 15 и 12 в десятичной форме). – Morwenn

ответ

4

Два числа считаются последовательны в сером коде, если они отличаются только один бит в двоичном представлении, например 111 и 101 отличаются только вторым битом. Функция, которую вы проверили, если два входных байта имеют только один бит, что делает их разными. Таким образом, 111 и 101 возвратят 1 из функции, тогда как 111 и 100 вернутся 0.

XOR используется для определения различий между обоими числами; XOR дает 1, когда бит различны и 0 в противном случае, например. 1111 XOR 1011 даст 0100. Таким образом, с XOR каждая разность бит подсвечивается 1 в этой позиции. Если оба числа являются последовательными серыми кодами, тогда в результате XOR должно быть только 1. Более одного из них означают множественные различия, которые не соответствуют критерию. Результат XOR сохраняется в переменной x.

Следующая задача - подсчитать количество единиц 1 - следовательно, переменную count. Если вы попробуете другие пары серого кода (большей длины бит), вы заметите, что полученное значение XOR всегда будет в этом формате (пренебрегая ведущими нулями): 10, 100, 1000 и т. Д. В принципе, 1, за которым следуют нули или в другими словами, всегда сила 2.

Если эти образцы XOR-результатов были уменьшены на 1, вы получите: 01, 011, 0111 и т. д. Если эти новые значения были ANDed с исходными результатами XOR, 0 будет результат каждый раз. Это логика, реализованная в вашем решении: для последовательной пары серого кода цикл while будет выполняться только один раз (и приращение count), после чего он завершится, потому что x стал 0. Итак, count = 1 в конце. Для не последовательной пары цикл будет выполняться более одного раза (попробуйте), а count будет больше 1 в конце.

Функция использует это как основу для возврата 1, если count == 1 и 0 в противном случае. Немного неясным, но он выполняет свою работу.

1

Это означает, что два номера отличаются ровно одним битом.

Таким образом, решение начинается с xor'ing двух чисел. Операция xor приводит к 1, где бит операндов отличается, иначе нулевой.

Так что вам нужно подсчитать количество бит в результатах xor и сравнить с 1. Вот что делает ваш загруженный пример. Этот метод подсчета 1 в двоичном числе является довольно известным методом Брайана Кернигана. Состояние x = (byte)(x & (x-1)) - это бит-магия, которая сбрасывает бит 1 разряда до нуля. There are lots of others.

В качестве альтернативы вы можете найти таблицу из 8 возможных байтов с 1 бит.

byte one_bit_bytes[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; 
1

Это очень неинтуитивный способ подсчитать, сколько бит в двоичном числе равно «1».

Для этого требуется знание бинарной арифметики. Начнем с того, что происходит, когда вы вычесть 1 для десятичного числа, которое записывается на «1», а затем одним или несколькими нулями: вы получите последовательность 9-х, длина которой равна числу нулей:

1000000 - 1 = 999999 

Подобное происходит с двоичными числами. Если вы вычитаете 1 из неотрицательного двоичного числа, все младшие цифры «0» заменяются на «1», а «1» перед нулевыми номерами заменяется на ноль. Это следует из того, как заимствование выполняется в двоичном формате. Пример:

0101_0000_0001_0000 - 1 = 0101_0000_0000_1111 
aaaa aaaa aaab cccc -> aaaa aaaa aaab cccc 

Обозначение: Подчеркивает для улучшения удобочитаемости. Все цифры, которые появляются над буквой а, не изменяются. Цифра «1», которая появляется над буквой b, изменяется на «0». А цифры «0», которые появляются над буквой c, меняются на «1».

Следующий шаг состоит в выполнении побитовой операции И с двумя числами (X) и (X-1). С описанным выше арифметическим свойством на каждой итерации имеется ровно одна цифра «1», которая исчезает из числа (начиная с правого, то есть наименее значимого).

Считая количество итераций, мы можем узнать, сколько бит «1» было первоначально представлено в числе X. Итерация прекращается, когда переменная X равна нулю.

Другие пользователи не ответили на поводу о серых кодах. Мой ответ объясняет, как работает «подсчет бит» (после XOR'ing двух значений).

0

Вот наивная тест для конкретного кода Грея монотонного упорядочения (двоичный отраженный код Грея):

// convert Gray code binary number to base 2 binary number 
int Base2(byte Gray){ Gray^=Gray>>4; Gray^=Gray>>2; return Gray^=Gray>>1; } 

// test if Gray codes are consecutive using "normal" base 2 numbers 
boolean GraysAdjacent(byte x, byte y){ return 1 == abs(Base2(x)-Base2(y)); } 

видеть особенно этот ответ (лучше всего):
How to find if two numbers are consecutive numbers in gray code sequence

закодированный в C, как :

int GraysTouch(byte x, byte y){ return !((x^y^1) && (x^y^(y&-y)<<1)); } 

// test   x marks the spots! (where they touch!) 
for(int i=31; i>-1; --i) 
    for(int j=31; j>-1; --j) 
    Serial.print((String)(GraysTouch(i^i>>1, j^j>>1)?"x":".") + 
         (GraysTouch(j^j>>1, i^i>>1)?"X":".") + (j?"":"\n")); 

Как это работает: ... будет объяснено и не код OP, потому что он очень подозрительный (см. Комментарий ниже).

Свойство XOR, ака оператора ^, что биты, которые соответствуют являются 0 и биты, которые отличаются 1.

1^0 == 0^1 == 1 
1^1 == 0^0 == 0 

Кроме того, на некоторое время, 0 XOR b работает как тождественной функции или просто b
и
1 XOR b работает как дополнение (без комплиментов, пожалуйста) функции или ~b.

id(x)  == x == x^0 
opposite(x) == ~x == x^11111111  Why eight 1's? Are eight enough? 

При сравнении двух битовых строк с XOR, биты, которые отличаются XOR в 1, в противном случае биты MUST матч и XOR является 0:

 0101     0001111001100111000 
XOR 0011   XOR 0001111001100000111 
    ------    --------------------- 
    0110     0000000000000111111 

Это объясняет x^y часть из код выше.
----------------------------------------------- -----------------------
Отклонение:
n^n>>1 выполняет быструю конвертацию двоичных чисел базы 2 в двоичные числа серого кода, используемые здесь.

Также обратите внимание, насколько сильно это f(a,b)=a^b^b=a является идемпотентным для любых b!
На месте своп находится a=a^b; b=a^b; a=a^b;.
Unrolled c=a^b; d=c^b; e=c^d; ie. d=a^b^b=a; e=a^b^a=b;
---------------------------------------------- ------------------------

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

Примеры:

Johnson 
    Code 
    000   000   000   000 
    001   001   001   100 
    011   101   011   110 
    111   111   010   010 
    110   011   110   011 
    100   010   111   111 
       110   101   101 
       100   100   001 
          ^^^ 
         this Gray coding 
        is the one used here 

Изучите его внимательно.

Случай 1
Когда низшего порядка бит последовательных чисел, x и y, для любой из кодов Грея, различны, остальные должны быть одинаковыми! Это определение серого кода. Это означает, что x^yдолжен выглядеть 0000 ... 0001.

Помните о дополнении, функции ~ aka 1^b? Для тестирования последнего бита x^y составляет XOR 'd с 1.

Этим объясняется x^y^1.
-------------------------------------------

Корпус 2
Местоположение другого бита в последовательных серых кодовых номерах x и y не является младшим разрядом. Посмотрите внимательно на последовательные номера серого кода.

001  010  101  lower order bits all match 
011  110  111 
    |  |   | <-- | mark location of lowest 1 
010  100  010 <-- XOR's 

Интересно, что в это код Грея, когда низкие биты порядка совпадают в x и y, так что тоже делает расположение низшего порядка 1.

Еще более интересным является то, что для последовательных чисел, биты всегда разные (для это Серого кода) в битовой позиции заказа следующего выше!

Так, x^y выглядит ???...?1000...0 где 1000...0 должен иметь по крайней мере один 0, 10 (почему?) И ???...? являются загадка бит, что для последовательных цифр коды Грея должна быть 000...0. (Почему? Е. Быть последовательными x^y должны выглядеть ...)

Наблюдение что

x^y looks like ???...?100...0 if and only if 
x and y look like ???...?:10...0 
          | <-- remember? the 1 location !! 

| местоположение можно найти либо x&-x или y&-y. (Почему? Почему должен ли - быть сделано с помощью комплемента машины к 2-?)
Однако : место должно быть проверено, что 1 (почему?) И ???...? являются 000...0. (Почему?)

Так,

x^y  looks like ???...?100...0 and 
(y&-y)<<1 looks like 000...0100...0 

и это объясняет тест x^y^((y&-y)<<1).
----------------------------------------------- --------------------

Почему это работает: ... является следствием свойств конкретного кода Gray, используемого здесь. Экзамен и объяснение слишком сложны для того, чтобы объяснить, почему этот серый код должен иметь эти свойства.

--------------------------------------------- -------------------------
Комментарий к неадекватности предыдущих ответов из-за проблем с кодом OP.

Caveat 1: Просто быть явным, алгоритм в вопросе Ор по:

private static int graycode(byte term1, byte term2) { 
    byte x = (byte)(term1^term2); // why use XOR? 
    int count = 0; 
    while(x!=0) 
    { 
    x = (byte)(x &(x-1)); // why use bitwise operator? 
    count++;    // what is count? 
    } 
    return count == 1; 
} 

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

Если по последовательным кодам подразумевается, что коды Grey используются для перечисления монотонного порядка, возникает проблема.

В частности, код будет возвращать true для всех этих пар:

000, 001 or 000, 010 or 000, 100 

так упорядочение может быть 001, 000, 010 но где можно 100 идти? Алгоритм сообщает (правильно), что «последовательность» 100 с любым из 001 or 010 - false.

Таким образом 100 должен непосредственно предшествовать или следовать 000 в перечислении, но не может непосредственно предшествовать или следовать за 001 или 010. DOH !!!

Caveat 2: Примечание x = (byte)(x & (x-1)) сбрасывает низкий порядка 1 бит x к нулю.

рефов:

Gray code increment function
Deriving nth Gray code from the (n-1)th Gray Code
https://electronics.stackexchange.com/questions/26677/3bit-gray-counter-using-d-flip-flops-and-logic-gates
How do I find next bit to change in a Gray code in constant time?
How to find if two numbers are consecutive numbers in gray code sequence