判断32位signed int是否为2的幂

时间:2011-09-09 13:37:31

标签: c binary logic bit-manipulation

我需要确定带符号的32位数是否为2的幂。到目前为止,我知道要做的第一件事是检查它是否为负,因为负数不能是2的幂。 然后我需要看看下一个数字是否有效等等......所以我能够这样写:

// Return 1 if x is a power of 2, and return 0 otherwise.
int func(int x)
{
     return ((x != 0) && ((x & (~x + 1)) == x));
}

但是对于我的任务,我只能使用其中的20个操作符:

! ~ & ^ | + << >>

和NO等式语句或循环或转换或语言结构。

所以我试图转换相等的部分,我知道!(a ^ b)与a == b相同,但我似乎无法完全弄明白。关于如何将其转换为允许的运营商的任何想法?

6 个答案:

答案 0 :(得分:4)

蒂姆的评论使我感到惭愧。让我试着帮你自己找到答案。

在位操作方面x是2的幂是什么意思?这意味着只有一个位设置为1.我们怎么能做这样的技巧,将该位转为0,另一些可能转为1?那么&amp;会给0?单表达?如果你发现 - 你赢了。

答案 1 :(得分:4)

试试这些想法:

  • ~!!x+1会给出一个掩码:如果x==0则为0,如果为x!=0则为-1。
  • (x&(~x+1))^x如果x最多设置1位则为0,否则为非零,除非~xINT_MIN,在这种情况下结果未定义...您可以将其拆分为多个部分,通过位移来避免这种情况,但我认为您将超出操作限制。
  • 您还需要检查符号位,因为负值不是2的幂......
顺便说一句,听起来你的教练不知道签名溢出是C中的UB。他应该为无符号整数编写这些问题。即使你想在语义上将值视为已签名,你需要使用无符号算术来执行这样的有意义的按位运算。

答案 2 :(得分:1)

想想这个...... 2减去1的任何幂都是一串0,后跟一串1s。您可以通过x + ~0实现减1。想想1s的字符串从单一的1开始,其中2的幂是2。

答案 3 :(得分:1)

int ispower2(int x)
{

    int ispositive= ! ( (x>>31) ^ 0) & !!(x^0);         
    int temp= !((x & ~x+1) ^ x);
    return temp & ispositive;

}

答案 4 :(得分:1)

首先,在您的解决方案中,应该是

return ((x > 0) && ((x & (~x + 1)) == x));

因为负数不能为2的幂。 根据您的要求,我们需要将“>”,“ &&”,“ ==”转换为允许的运算符。

首先考虑“>”,它的符号位为1且不为0时为> 0的整数;所以我们考虑

~(x >> 31) & (x & ~0)

如果x为正数,则上述表达式将返回非零数。请注意〜0 = -1,即0x11111111。我们使用x&〜0来检查此整数在每个数字上是否都为0。

第二,我们考虑“ &&”。 AND非常简单-我们只需要获取0x01和0x01即可返回1。因此,在这里,我们需要在第一个答案前面添加(!!),如果它返回一个非零数字,则将其更改为0x01。

最后,我们考虑“ ==“。要测试A和B的公平性,我们只需要做

!(A ^ B)

所以最后我们有了

return (!!(~(x >> 31) & (x & ~0))) & (!((x&(~x+1)) ^ x))

这似乎是一个作业问题。请不要简单地复制和粘贴。我的回答有点尴尬,可能会有所改善。

答案 5 :(得分:0)

在C中使用按位运算符来解决一些问题是有趣和有效的。在这个问题中,我们需要处理两个检查:

  1. 签名检查。如果为负,则返回0;否则返回1;

    ! (x>&gt;&gt;&amp; ox1)&amp; !(!x)

    / *这个操作。提取x中的符号位。但是,&gt;&gt;在这种情况下将是算术。这意味着在最后一位(LSB)之前将有所有1。对于负int,它是oxFFFFFFFF( - );否则,oxFFFFFFFE(+)。 AND ox1 op。纠正&gt;&gt;到ox1( - )或ox0(+)。逻辑!将ox1( - )和ox0(+)分别变为0或1。 !(!x)确保0不是电源(2)* /

  2. isPower(2)检查。如果是,返回1;否则为0.

    !(x&amp;(~x + ox1)^ x)

    / *这个操作。 isPower(2)检查。 x&amp; (~x + ox1)返回x,当且仅当x是幂(2)时。例如:x = ox2和~x + ox1 = oxFFFFFFFE。 x&amp; (~x + ox1)= ox2;如果x = ox5且~x + ox1 = oxFFFFFFFB。 x&amp; (~x + ox1)= ox1。因此,ox2 ^ ox2 = 0;但是ox5 ^ ox1 = ox4。的! op将0和其他分别变为1和0。* /

  3. 最后一个AND op。 1到2之间的检查将生成isPower(2)函数的结果。