鱼C论坛

 找回密码
 立即注册
查看: 990|回复: 4

[已解决]关于‘&’的问题

[复制链接]
发表于 2019-8-3 00:33:40 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
  1. // 检查num是否2的N次方
  2.         // 注意,这里是&,不是&&
  3.         // &是按位与操作,1&1==1,0&1==0,0&0 == 0
  4.         if (num & num - 1)
  5.         {
  6.                 printf("参数队伍的数量必须是2的N次方!\n");
  7.                 return -1;
  8.         }
复制代码

这个代码的用处是过滤不是2的n次方的数,我看了第三个注释的例子,看了半天越看越不明白
帅(美)的帮忙解释一下
(这个例子是s1e35的课后作业)
最佳答案
2019-8-3 10:21:58
本帖最后由 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
  1. if(num == 0 || num == -128)//因为我把num当成了一个8位数据所以才是-128,其它类型的数据的话这里就不是-128了
  2. {
  3.     printf("参数队伍的数量必须是2的N次方!\n");
  4.     return -1;
  5. }
  6. else if (num & num - 1)
  7. {
  8.      printf("参数队伍的数量必须是2的N次方!\n");
  9.      return -1;
  10. }
复制代码

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2019-8-3 09:12:26 | 显示全部楼层
理解 num+num-1不?
那么你就应该理解 num & num -1 ,很简单嘛 & 是运算运算术 “与运算” 不懂  “与运算” 上网找资源吧
&是位运算符
&&是布尔逻辑运算符。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-8-3 10:21:58 | 显示全部楼层    本楼为最佳答案   
本帖最后由 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
  1. if(num == 0 || num == -128)//因为我把num当成了一个8位数据所以才是-128,其它类型的数据的话这里就不是-128了
  2. {
  3.     printf("参数队伍的数量必须是2的N次方!\n");
  4.     return -1;
  5. }
  6. else if (num & num - 1)
  7. {
  8.      printf("参数队伍的数量必须是2的N次方!\n");
  9.      return -1;
  10. }
复制代码

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2019-8-3 22:30:34 | 显示全部楼层
Neverturnback 发表于 2019-8-3 10:21
// 检查num是否2的N次方
        // 注意,这里是&,不是&&
        // &是按位与操作,1&1==1,0&1==0 ...

谢谢!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-8-3 23:02:14 | 显示全部楼层

不用谢加油吖
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-5-4 08:38

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表