I've written a function trailing_zeroes(int n)
that returns the number of the trailing zeroes in the binary representation of a number.
Example: 4
in binary is 100
, so the function in this case returns 2
.
unsigned trailing_zeroes(int n) {
unsigned bits;
bits = 0;
while (n >= 0 && !(n & 01)) {
++bits;
if (n != 0)
n >>= 1;
else
break;
}
return bits;
}
The reason of the if
statement is because in case n
equals to 0, there will be a loop.
I think it's pretty ugly this code written like this; is there a better way?
I want to avoid the break
statement inside the while
, because a lot of people told me that using that statement inside while/for
sometimes could be "informal". I thought to rewrite the function like this, but I don't think it's the best way to do it:
unsigned bits;
if (n == 0)
return bits = 1;
bits = 0;
while (!(n & 01)) {
++bits;
n >>= 1;
}
Your function is incorrect: it still has an infinite loop for 0
. The test should be:
while (n > 0 && !(n & 1))
Note that you cannot handle negative numbers with this approach, hence your function should probably take an unsigned
number argument, or you could convert the argument to unsigned
.
Your function should special case 0
and use a simpler loop:
unsigned trailing_zeroes(int n) {
unsigned bits = 0, x = n;
if (x) {
while ((x & 1) == 0) {
++bits;
x >>= 1;
}
}
return bits;
}
The above function is very simple and easy to understand. It is quite fast if the result is small. The value returned for 0
is 0
as in your function, which is questionable as 0
really has as many trailing zeroes as value bits in the unsigned
type.
There is a more efficient approach with a constant number of steps:
unsigned trailing_zeroes(int n) {
unsigned bits = 0, x = n;
if (x) {
/* assuming `x` has 32 bits: lets count the low order 0 bits in batches */
/* mask the 16 low order bits, add 16 and shift them out if they are all 0 */
if (!(x & 0x0000FFFF)) { bits += 16; x >>= 16; }
/* mask the 8 low order bits, add 8 and shift them out if they are all 0 */
if (!(x & 0x000000FF)) { bits += 8; x >>= 8; }
/* mask the 4 low order bits, add 4 and shift them out if they are all 0 */
if (!(x & 0x0000000F)) { bits += 4; x >>= 4; }
/* mask the 2 low order bits, add 2 and shift them out if they are all 0 */
if (!(x & 0x00000003)) { bits += 2; x >>= 2; }
/* mask the low order bit and add 1 if it is 0 */
bits += (x & 1) ^ 1;
}
return bits;
}
Note that we could handle any larger int
size by changing the first step to
while (!(x & 0x0000FFFF)) { bits += 16; x >>= 16; }
Some compilers have a built-in function __builtin_ctz()
to count the number of trailing zeroes using very efficient assembly code. It is not a C Standard function but at the cost of reduced portability, you might want to use it if it is available. Check your compiler's documentation.
Here is the abstract from GCC documentation:
Built-in Function:
int __builtin_ctz (unsigned int x)
Returns the number of trailing 0-bits in
x
, starting at the least significant bit position. Ifx
is0
, the result is undefined.