C 此按位操作如何检查2的幂?

C 此按位操作如何检查2的幂?,c,math,bit-manipulation,C,Math,Bit Manipulation,我在看一些应该是琐碎的代码——但我的数学在这里让我非常不及格 下面是一个条件,用于检查一个数字的幂是否为2,方法如下: if((num != 1) && (num & (num - 1))) { /* make num pow of 2 */ } 我的问题是,在num和num-1之间使用按位AND如何确定一个数字是否是2的幂 如果X=1000,那么X-1=0111。1000&&0111是0000 每一个2的幂的数字X都有一个X-1,它在X的位置上有一个0。0和1的按位A

我在看一些应该是琐碎的代码——但我的数学在这里让我非常不及格

下面是一个条件,用于检查一个数字的幂是否为2,方法如下:

if((num != 1) && (num & (num - 1))) { /* make num pow of 2 */ }
我的问题是,在num和num-1之间使用按位AND如何确定一个数字是否是2的幂

如果X=1000,那么X-1=0111。1000&&0111是0000

每一个2的幂的数字X都有一个X-1,它在X的位置上有一个0。0和1的按位And始终为0

如果数字x不是二的幂,例如0110。x-1为0101,和为0100

对于0000-1111范围内的所有组合,这将导致

   X  X-1 X && X-1  
0000 1111 0000   
0001 0000 0000 
0010 0001 0000
0011 0010 0010
0100 0011 0000
0101 0100 0100
0110 0101 0100
0111 0110 0110
1000 0111 0000
1001 1000 1000
1010 1001 1000
1011 1010 1010
1100 1011 1000
1101 1100 1100
1110 1101 1100
1111 1110 1110

不需要对1进行单独检查。

2减去1的任何幂都是1:(2N-1=111….b)

以8为例。1000&0111=0000

所以这个表达式测试一个数字是否不是2的幂。

解释得很好

此外,给出的表达式认为0是2的幂。来解决这个问题
!(x&(x-1))&&x取而代之。

第一个案例将检查20==1

对于其他情况,
num&(num-1)
起作用:

也就是说,如果你取任何一个数字,并从一个较低的数字中屏蔽位,你将得到两种情况中的一种:

  • 如果该数字已经是2的幂,那么少一个将产生一个只设置了较低阶位的二进制数。使用
    &
    不会有任何作用

    • 以8为例:
      0100&(0100-1)
      -->
      (0100&0011)
      -->
      0000
  • 如果数字不是2的幂,那么少一个将不会触及最高位,因此结果将至少是小于num的最大幂

    • 以3为例:
      0011和(0011-1)
      -->
      (0011和0010)
      -->
      0010

    • 以13为例:
      1101和(1101-1)
      -->
      (1101和1100)
      -->
      1100


  • 因此,实际表达式会找到所有不是2的幂的东西,包括20。

    下面的C程序会找出数字是否是2的幂,以及2的哪个幂,数字是

    #include<stdio.h>
    void main(void)
    {
        unsigned int a;
        unsigned int count=0
        unsigned int check=1;
        unsigned int position=0;
        unsigned int temp;
        //get value of a
        for(i=0;i<sizeof(int)*8;i++)//no of bits depend on size of integer on that machine
        {
            temp = a&(check << i);
            if(temp)
            {
                position = i;
                count++;
            }
        }
        if(count == 1)
        {
            printf("%d is 2 to the power of %d",a,position);
        }
        else
        {
            printf("Not a power of 2");
        }
    }
    
    另一种方式可以是这样的:-

    如果我们取一个2的幂的数字的补码

    例如,8的补码,即0x1000,我们得到0x0111,再加上1,我们得到

    相同的数字,如果是这样的话,这个数字是2的幂

        void IsPowerof2(int i)
        {
        if(!((i-1)&1))
        {
        printf("%d" is a power of 2, i);
        }
        }
    
        void IsPowerof2(int i)
        {
        if(((~1+1)&i) == 1)
        {
        printf("%d" is a power of 2,i):
        }
        }                                                     
    

    它确定整数是否为2的幂。如果
    (x&(x-1))
    为零,则数字为2的幂

    比如说,, 设
    x
    为8(
    1000
    二进制);然后
    x-1
    =7(
    0111

    if 1000
    &   0111
    ---------------
    0000
    
    C程序演示:

    #include <stdio.h>
    
    void main()
    {
        int a = 8;
        if ((a&(a-1))==0)
        {
            printf("the bit is power of 2  \n");
        }
        else 
        {
            printf("the bit is not power of 2\n");
        }
    }
    

    这输出
    位不是2的幂

    我更喜欢这种依赖于2的补码的方法:

    #include <stdio.h>
    
    void main()
    {
        int a = 7;
        if ((a&(a-1))==0)
        {
            printf("the bit is power of 2  \n");
        }
        else 
        {
            printf("the bit is not power of 2\n");
        }
    }
    
    bool checkPowTwo(int x){
        return (x & -x) == x;
    }
    

    假设n是给定的数字,
    如果n是2的幂(n&&!(n&(n-1))将返回1,否则将返回0

    ,但当然需要检查0,因为0不是2的幂,但测试时就好像它是一样。这里有几件事-首先,我认为您正在使用
    &
    的一些地方,您的意思是
    &
    n&(n-1)
    几乎所有地方都是1(除了n=0和n=1之外,对吗?)第二,1是2的幂,但“需要”取决于我们从未见过的上下文(“如果幂为正/自然”,则为true,反之为“如果正好设置了一位”,则为true)这与个人无关,至少是十年前的事了。在这个问题上可以找到更多的信息:这显然取决于
    num
    的类型-这里的大多数答案都假设它是一个无符号整数类型,其中按位运算定义得很好。不,这是错误的。没有x使得2**x=0。因此x不是2.Ac的幂实际上,不需要检查特殊情况
    num==1
    (2^0=1)。对于这种情况(num&(num-1))=(1&0)=0。第二点的解释不正确,(num-1)可能是2的幂,但不一定如此。结果总是非零的原因是,操作总是可以在不接触最高位的情况下进行,并且至少该位会显示在输出中。Ismael Luceno的评论是对上述观察结果的更好解释,如上文评论所述,第2点中的陈述:“返回2的最高幂不大于num”是不正确的。它应该更准确地读为“返回至少2的最高幂不大于num”。我已经对这个答案进行了编辑,它正在等待同行评审。请解释这是如何回答这个问题的。“这里有一些其他方法可以做同样的事情。”“未提供所请求的启示。如果数据类型为int受min value限制,则在1.num=0和num=-2147483648的情况下为角型。当num==0时,num不是2次幂。”
    bool checkPowTwo(int x){
        return (x & -x) == x;
    }