Утверждается следующая функция, чтобы оценить, является ли число целым числом 4. Я не совсем понимаю, как это работает?
bool fn(unsigned int x)
{
if ( x == 0 ) return false;
if ( x & (x - 1) ) return false;
return x & 0x55555555;
}
Утверждается следующая функция, чтобы оценить, является ли число целым числом 4. Я не совсем понимаю, как это работает?
bool fn(unsigned int x)
{
if ( x == 0 ) return false;
if ( x & (x - 1) ) return false;
return x & 0x55555555;
}
Первое условие исключает 0, что, очевидно, не является степенью 4, но неправильно пройдет следующие два теста. (EDIT: Нет, это не так, как указано. Первый тест является избыточным.)
Следующий - хороший трюк: он возвращает true тогда и только тогда, когда это число равно 2. Сила двух характеризуется наличием только одного бита. Число с одним битом минус один приводит к числу со всеми битами, предшествующими установленному биту (т.е. 0x1000 минус один - 0x0111). И эти два числа, и вы получите 0. В любом другом случае (то есть не в силе 2) будет по крайней мере один бит, который перекрывается.
Итак, в этот момент мы знаем, что она равна 2.
x & 0x55555555
возвращает ненулевой (= true), если какой-либо четный бит установлен (бит 0, бит 2, бит 4, бит 6 и т.д.). Это означает, что мощность 4 (т.е. 2 не проходит, но 4 прохода, 8 не проходит, 16 проходов и т.д.).
Каждая степень 4 должна быть в форме 1, за которой следует четное число нулей (двоичное представление): 100... 00:
100 = 4
10000 = 16
1000000 = 64
1-й тест ( "если" ) очевиден.
При вычитании 1 из числа формы XY100... 00 вы получаете XY011... 11. Итак, второй тест проверяет, есть ли в этом номере более одного "1" бита (XY).
Последний тест проверяет, находится ли этот единственный "1" в правильном положении, т.е. бит # 2,4,6 и т.д. Если это не так, маскировка (&) вернет ненулевой результат.