Следующее основано на концепции, что если вы AND
битовая последовательность со смещенной версией самого себя, вы фактически удаляете трейлинг 1 из ряда последовательных 1.
11101111 (x)
& 11011110 (x << 1)
----------
11001110 (x & (x << 1))
^ ^
| |
trailing 1 removed
Повторение этого N
раз уменьшит любую последовательность с N
последовательных 1 до 0x00
.
Итак, чтобы посчитать количество последовательных 1:
int count_consecutive_ones(int in) {
int count = 0;
while (in) {
in = (in & (in << 1));
count++;
}
return count;
}
Для подсчета количества последовательных 0 просто инвертируйте и одну и ту же процедуру.
int count_consecutive_zeros(int in) {
return count_consecutive_ones(~in);
}
Подтверждение концепции: http://ideone.com/Z1l0D
int main(void) {
printf("%d has %d consecutive 1's\n", 0, count_consecutive_ones(0));
printf("%d has %d consecutive 0's\n", 0, count_consecutive_zeros(0));
/* 00000000 11110000 00000000 00000000 -> If it is 0 then length will be 20 */
printf("%x has %d consecutive 0's\n", 0x00F00000, count_consecutive_zeros(0x00F00000));
/* 11111111 11110000 11110111 11111111 -> If it is 1 then length will be 12 */
printf("%x has %d consecutive 1's\n", 0xFFF0F7FF, count_consecutive_ones(0xFFF0F7FF));
}
Выход:
0 has 0 consecutive 1's
0 has 32 consecutive 0's
f00000 has 20 consecutive 0's
fff0f7ff has 12 consecutive 1's