Магическое число в отраженном коде Грея в двоичное преобразование

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

unsigned short grayToBinary(unsigned short num)
{
        unsigned short temp = num ^ (num>>8);
        temp ^= (temp>>4);
        temp ^= (temp>>2);
        temp ^= (temp>>1);
        return temp;
}

Затем я изменил код, чтобы он работал для любого стандартного типа unsigned. Вот что я написал:

template<typename Uint>
Uint grayToBinary(Uint value)
{
    for (Uint mask = sizeof(Uint)*4 ; mask ; mask >>= 1)
    {
        value ^= value >> mask;
    }
    return value;
}

Алгоритм, кажется, отлично работает для каждого unsigned стандартного типа. Однако при его написании я инстинктивно использовал sizeof(Uint)*4, так как имело смысл, что конечное условие будет зависеть от размера шрифта, но правда в том, что я понятия не имею, что на самом деле представляет sizeof(Uint)*4. Пока это магическое число, которое я написал инстинктивно, но я не могу объяснить, почему оно работает с *4, а не с каким-либо другим коэффициентом.

Кто-нибудь знает, чему на самом деле соответствует это магическое число?


person Morwenn    schedule 21.02.2014    source источник
comment
Подождите, вы хотите сказать, что написали этот код, но не понимаете, почему он работает?   -  person Oliver Charlesworth    schedule 21.02.2014
comment
@OliCharlesworth это на удивление часто встречается в CS   -  person Andreas Grapentin    schedule 21.02.2014
comment
нет, он говорит, что думает, что это работает.   -  person Karoly Horvath    schedule 21.02.2014
comment
i.imgur.com/qsLx1Ip.jpg   -  person Andreas Grapentin    schedule 21.02.2014
comment
@OliCharlesworth Ну, я адаптировал уже работающий код, который я не понял на 100%, и он работает (по крайней мере, все мои модульные тесты работают). Я знаю, это позор ^^   -  person Morwenn    schedule 21.02.2014


Ответы (1)


4 оказывается 8 / 2 [необходима цитата] или CHAR_BIT / 2.

Ваш алгоритм декодирования кода Грея начинает с того, что берет левую половину данного целочисленного типа и сдвигает ее к правой половине типа, которая оказывается на sizeof(type) * (CHAR_BIT / 2) бита вправо, что вы и видите.

Как указано в комментариях, std::numeric_limits<type>::digits / 2 было бы более идиоматичным решением для C++.

person Andreas Grapentin    schedule 21.02.2014
comment
Должен ли я предположить, что 8 означает CHAR_BIT? - person Morwenn; 21.02.2014
comment
8 обозначает количество битов в байте. - person Marius Bancila; 21.02.2014
comment
Как и CHAR_BIT. Примерно это я и имел в виду :) - person Morwenn; 21.02.2014
comment
Кстати, для тех, кто хочет идиоматическое решение C++, вместо sizeof(type) * (CHAR_BIT / 2) было бы лучше использовать std::numeric_limits<type>::digits / 2. - person Morwenn; 22.02.2014
comment
@Morwenn, это отличная идея. Вы не возражаете, если я добавлю это к моему ответу? - person Andreas Grapentin; 22.02.2014
comment
@AndreasGrapentin Я не вижу проблемы. Я буду счастлив, если у людей будет доступ к наилучшему ответу: p - person Morwenn; 23.02.2014