Оценить, является ли число целым числом 4

Утверждается следующая функция, чтобы оценить, является ли число целым числом 4. Я не совсем понимаю, как это работает?

bool fn(unsigned int x)
{
if ( x == 0 ) return false;
if ( x & (x - 1) ) return false;
return x & 0x55555555;
}

Ответы

Ответ 1

Первое условие исключает 0, что, очевидно, не является степенью 4, но неправильно пройдет следующие два теста. (EDIT: Нет, это не так, как указано. Первый тест является избыточным.)

Следующий - хороший трюк: он возвращает true тогда и только тогда, когда это число равно 2. Сила двух характеризуется наличием только одного бита. Число с одним битом минус один приводит к числу со всеми битами, предшествующими установленному биту (т.е. 0x1000 минус один - 0x0111). И эти два числа, и вы получите 0. В любом другом случае (то есть не в силе 2) будет по крайней мере один бит, который перекрывается.

Итак, в этот момент мы знаем, что она равна 2.

x & 0x55555555 возвращает ненулевой (= true), если какой-либо четный бит установлен (бит 0, бит 2, бит 4, бит 6 и т.д.). Это означает, что мощность 4 (т.е. 2 ​​не проходит, но 4 прохода, 8 не проходит, 16 проходов и т.д.).

Ответ 2

Каждая степень 4 должна быть в форме 1, за которой следует четное число нулей (двоичное представление): 100... 00:

100 = 4

10000 = 16

1000000 = 64

  • 1-й тест ( "если" ) очевиден.

  • При вычитании 1 из числа формы XY100... 00 вы получаете XY011... 11. Итак, второй тест проверяет, есть ли в этом номере более одного "1" бита (XY).

  • Последний тест проверяет, находится ли этот единственный "1" в правильном положении, т.е. бит # 2,4,6 и т.д. Если это не так, маскировка (&) вернет ненулевой результат.