我需要确定带符号的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相同,但我似乎无法完全弄明白。关于如何将其转换为允许的运营商的任何想法?
答案 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,否则为非零,除非~x
为INT_MIN
,在这种情况下结果未定义...您可以将其拆分为多个部分,通过位移来避免这种情况,但我认为您将超出操作限制。答案 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中使用按位运算符来解决一些问题是有趣和有效的。在这个问题中,我们需要处理两个检查:
签名检查。如果为负,则返回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)* /
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。* /
最后一个AND op。 1到2之间的检查将生成isPower(2)函数的结果。