我一直在搞乱我在互联网上找到的按位操作员问题并发现了一个完全让我感到困惑的操作员。
int rpwr2(int x, int n)
{
//Legal ops: ! ~ ^ | + << >>
//My attempt at a solution:
int power = (1 << n) + ~0;
return x & power;
}
答案 0 :(得分:3)
harold的suggestion几乎是正确的,但对于负-result
,我们需要
x
result - (1 << n)
除非结果为0.在二进制中,
x & ((1 << n) - 1)
对于每个x
(和2^n
足够小,x
正常工作),与n
modulo 1 << n
一致。这是区间x
中[0, 2^n)
残留等级的代表。
要求是为负(-2^n, 0]
得到负(非正,更准确)余数(在x
区间内)。这意味着,对于不是x
的倍数的否定2^n
,我们必须从2^n
中减去x & ((1 << n) - 1)
。
int rempwr2(int x, int n)
{
//Compute x%(2^n) for 0 <= n <= 30.
//Negative arguments should yield a negative remainder.
//Examples: rempwr2(15, 2) = 3; rempwr2(-35, 3) = -3;
//Legal ops: ! ~ ^ | + << >>
//My attempt at a solution:
int power = (1 << n) + ~0; // 2^n - 1
int mask = x >> 31;
int result = x & power;
return (x & power) + (((~((!!result) << n)) + 1) & mask);
}
如果x >= 0
,则mask = 0
和(x & power) + (whatever & mask) = (x & power)
是正确的结果。
对于x < 0
,我们必须减去1 << n
,除非result = 0
。
(!!result) << n
如果x
是2^n
的倍数,则为0,否则为2^n
。由于不允许直接减法,我们必须否定(-n = ~n + 1
在二的补码中),所以我们找到
(~((!!result) << n)) + 1
如果result = 0
,仍为0,否则为-2^n
,因此我们必须为否定x
添加。但是对于正x
,这也可以是非零值,因此我们必须在这种情况下使其无效,我们通过按位和mask
({{1}为0)来做并且为x >= 0
设置了所有位。