编写一个C函数,将一个数字向下舍入到下一个2的幂

KBE*_*KBE 11 c

我在接受采访时得到了以下问题:"编写一个C函数,将一个数字向下舍入到下一个2的幂".

我写了以下答案:

#include <stdio.h>

int next_pwr_of_2(int num)
{
    int tmp;

    do
    {
        num++;
        tmp=num-1;
    }
    while (tmp & num != 0);

    return num;
}

void main()
{
    int num=9;
    int next_pwr;
    next_pwr=next_pwr_of_2(num);
    printf(" %d \n",next_pwr);
}
Run Code Online (Sandbox Code Playgroud)

问题是:为什么程序do-while在达到11和10值时会退出循环?

axi*_*iom 28

优先考虑我的朋友,优先.

while ((tmp & num) != 0);

会解决它.(注意表达式周围的括号tmp & num)

!=优先级高于&,num != 0之前进行评估tmp & num.

如果跳过括号,则计算的表达式为: tmp & (num != 0)

  1. 圆第一次,tmp = 9 (1001)而且num != 01 (0001)这样&的计算结果为1(真),并继续循环.

  2. 现在在第二次迭代结束时,我们有,tmp = 10 (1010).num != 0再次为0001,因此1010 & 0001评估为0,因此循环中断.

是表格供参考.

优先顺序是相当不寻常的,因为注意到这里.一直发生:).

当然,你不必记住任何优先顺序,这只是为了帮助编译器在决定什么是第一次做,如果程序员不说清楚.您可以正确地将表达式括起来并避免出现这种情况.


das*_*ght 20

循环退出是因为您没有在您的条件周围放置括号.这应该教你不要把不必要的东西!= 0放在你的C/C++条件下.

不过,您可以简化代码.

首先,观察它temp等于先前的值num,因此您可以将循环更改为

int tmp;
do {
    tmp = mum++;
} while (tmp & num); // Don't put unnecessary "!= 0"
Run Code Online (Sandbox Code Playgroud)

其次,面试官可能想看看你是否熟悉这个小技巧:

v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v++;
Run Code Online (Sandbox Code Playgroud)

与您的代码可能需要多达1,000,000,000次操作完成不同,上述操作总是在12次操作(减量,增量,5次和5次OR)后完成.

  • 关于bit twiddling技巧:它取决于知道`int`中的位数.使用完全可移植的`v << = 1,您只会获得稍多的操作(可能更少); while((v&(v - 1))!= 0){v&= v - 1; }(除了这需要选择特殊情况,其中数字是2的幂).应该优先选择哪一个取决于上下文(当然,要么总是比建议的解决方案更好). (3认同)