Использование заданных побитовых операторов для воспроизведения функции - PullRequest
0 голосов
/ 03 ноября 2019

У меня есть вопрос, очень похожий на тот, что здесь Проверка битов целых чисел, чтобы увидеть, разделяют ли они двоичные числа со степенью 2 (только по битам) , однако вопрос был откровенно плохо сформулирован (поэтому яЯ не уверен, насколько они похожи), и ответ не был объяснен.

Попытка повторить эту функцию:

    int testdl4(int x) {
       int i;
       for (i = 1; i < 32; i+=2)
           if ((x & (1<<i)) == 0)
              return 0;
       return 1; 
    }

Используя только следующие побитовые операторы:!, ~, &, ^, |, +, << и >> (что означает отсутствие циклов или операторов if).

Ответ на вышеупомянутую ссылку (я думаю, тот же вопрос, но с циклом, начинающимся с 0) был:

return! ((X & 0x55555555) ^ 0x55555555);

И я считаю, что маску нужно изменить, чтобы она заработала, но я не уверен, что 2.

Может кто-нибудь решить, объяснить и объяснить?

1 Ответ

1 голос
/ 03 ноября 2019

Давайте начнем с написания того, что на самом деле делает ваш код, на английском языке:

If any odd numbered bit (from 1 to 31) is clear return 0; otherwise return 1.

Теперь "any odd numbered bit (from 1 to 31)" - это двоичное значение 10101010101010101010101010101010b, которое равно 0xAAAAAAAAUL. Обратите внимание, что это значение невозможно для 32-разрядных целых чисел со знаком, поэтому мы хотим использовать целые числа без знака длиной не менее 32 бит.

Если бит сброшен, то x & 0xAAAAAAAAUL не будет равен0xAAAAAAAAUL.

Это дает:

int testdl4(unsigned long x) {
    if( (x & 0xAAAAAAAAUL) != 0xAAAAAAAAUL) {
        return 0;
    }
    return 1;
}

Обратите внимание, что сюда входит if для получения того же поведения, что и ваш исходный код (например, возвращение 1 и отсутствие возвратаиспортил ненулевое значение).

Однако, логическое НЕ ! заставит ненулевое значение стать нулем, а нулевое значение - 1;так что вы можете сделать:

int testdl4(unsigned long x) {
    return !((x & 0xAAAAAAAAUL) ^ 0xAAAAAAAAUL);
}
...