尾随零的数量 [英] Number of trailing zeroes

查看:62
本文介绍了尾随零的数量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了一个函数 trailing_zeroes(int n),该函数以数字的二进制表示形式返回尾随零的数字.

I've written a function trailing_zeroes(int n) that returns the number of the trailing zeroes in the binary representation of a number.

示例:二进制格式的 4 100 ,因此该函数在此情况下返回 2 .

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;
}

if 语句的原因是因为如果 n 等于0,则会出现循环.

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?

我想避免在 while 中使用 break 语句,因为很多人告诉我,在 while/for 中使用该语句有时可能是非正式的".我本来想重写函数,但我认为这不是最好的方法:

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;
}

推荐答案

您的函数不正确:对于 0 ,它仍然具有无限循环.测试应该是:

Your function is incorrect: it still has an infinite loop for 0. The test should be:

while (n > 0 && !(n & 1))

请注意,您无法使用这种方法处理负数,因此您的函数可能应该使用 unsigned 数字参数,或者可以将参数转换为 unsigned .

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.

您的函数应为特殊情况 0 并使用更简单的循环:

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;
}

以上功能非常简单易懂.如果结果很小,那将是非常快的.与您的函数一样,为 0 返回的值是 0 ,这值得怀疑,因为 0 的尾随零实际上与 0中的值位一样多.code> unsigned 类型.

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 questionnable 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; }

某些编译器具有内置函数 __ builtin_ctz(),可使用非常有效的汇编代码来计算尾随零的数量.它不是C标准函数,但是以降低可移植性为代价,如果可用,您可能希望使用它.查看编译器的文档.

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.

以下是 GCC文档中的摘要:

内置函数: int __builtin_ctz(无符号int x)

从最低有效位位置开始,返回 x 中尾随0位的数目.如果 x 0 ,则结果不确定.

Returns the number of trailing 0-bits in x, starting at the least significant bit position. If x is 0, the result is undefined.

这篇关于尾随零的数量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆