关于‘&’的问题
// 检查num是否2的N次方// 注意,这里是&,不是&&
// &是按位与操作,1&1==1,0&1==0,0&0 == 0
if (num & num - 1)
{
printf("参数队伍的数量必须是2的N次方!\n");
return -1;
}
这个代码的用处是过滤不是2的n次方的数,我看了第三个注释的例子,看了半天越看越不明白
帅(美)的帮忙解释一下
(这个例子是s1e35的课后作业) 理解 num+num-1不?
那么你就应该理解 num & num -1 ,很简单嘛 & 是运算运算术 “与运算” 不懂“与运算” 上网找资源吧
&是位运算符
&&是布尔逻辑运算符。 本帖最后由 Neverturnback 于 2019-8-3 10:26 编辑
// 检查num是否2的N次方
// 注意,这里是&,不是&&
// &是按位与操作,1&1==1,0&1==0,0&0 == 0
if (num & num - 1) //首先 - 运算在C语言计算优先级第4级, & 按位与运算在优先级第8级,所以这里的运算顺序是num & (num - 1);
{
printf("参数队伍的数量必须是2的N次方!\n");
return -1;
}
分析:
1.首先分析这个过滤的数是一个正数:
一个数如果是2的N次方,那么这个数的二进制必定只有一个位上是1其它全是0:
比如: 0000 0001, 0000 0010, 0000 0100, 0000 1000。。。其它的就不例举了
2的N次方的数-1以后是:0000 0000, 0000 0001, 0000 0011, 0000 0111。。。(对应上面的例子)
按位与两个数 :0000 0000, 0000 0000,0000 0000,0000 0000。。。
讲到这边就可以看出来一个2的N次方的数按位与上本身-1的值就必定是0,在if(x)中,如果x为0就是假,非0就是真;所以if(num & num - 1)可以过滤出2的N次方的数,if判定为假这个数就是2的N次方,否则不为2的N次方
2。下面分析这个过滤的数是负数
2的N次方肯定是一个正数,所以负数不可能是2的N次方,那么这里为什么能过滤负数呢?
首先我们知道一个负数的二进制的最高位肯定是1,所以除了1000 000(即-128)以外,任何一个负数都不可能只有一个位上是1其它全是0的状况,举个例子:
num(-127):1000 0001
num - 1 :1000 0000
num&num-1 : 1000 0000
所以负数就会被这个算法过滤掉
3.两种特殊情况会导致这个算法失效:
(1)num = 0的情况
首先0不是2的N次方
但是0000 0000 & 任何数结果都必定是 0000 0000
所以if(num & (num - 1))就是假,但是0不是2的N次方所以这里就不能过滤0了
(2)num = -128
首先-128不是2的N次方
-128 = 1000 0000
-128 - 1 = 0111 1111
-128 & -128 - 1 = 0000 0000
所以if(num & num - 1)当num = -128的时候也是假,所以这里算法也失效了
综上正确的做法是在使用这个算法之前要先过滤掉0和-128
if(num == 0 || num == -128)//因为我把num当成了一个8位数据所以才是-128,其它类型的数据的话这里就不是-128了
{
printf("参数队伍的数量必须是2的N次方!\n");
return -1;
}
else if (num & num - 1)
{
printf("参数队伍的数量必须是2的N次方!\n");
return -1;
}
Neverturnback 发表于 2019-8-3 10:21
// 检查num是否2的N次方
// 注意,这里是&,不是&&
// &是按位与操作,1&1==1,0&1==0 ...
谢谢!{:10_281:} joker__ 发表于 2019-8-3 22:30
谢谢!
不用谢{:5_109:}加油吖
页:
[1]