我一直在弄亂我在互聯網上發現的按位運算符問題,並發現一個只是完全殘留下來的問題。按位餘數運算符
int rpwr2(int x, int n)
{
//Legal ops: ! ~^| + << >>
//My attempt at a solution:
int power = (1 << n) + ~0;
return x & power;
}
我一直在弄亂我在互聯網上發現的按位運算符問題,並發現一個只是完全殘留下來的問題。按位餘數運算符
int rpwr2(int x, int n)
{
//Legal ops: ! ~^| + << >>
//My attempt at a solution:
int power = (1 << n) + ~0;
return x & power;
}
harold的suggestion幾乎是正確的,但不是-result
,負x
,我們需要
result - (1 << n)
除非結果爲0。2的補
x & ((1 << n) - 1)
是x
模2^n
每x
(和n
小到足以讓1 << n
正常工作)。這是x
的殘差類別[0, 2^n)
的代表。
要求是爲負數x
獲得負數(非正數,更確切的)餘數(在區間(-2^n, 0]
中)。這意味着,對於不是2^n
的倍數的負數x
,我們必須從x & ((1 << n) - 1)
減去2^n
。
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
是0,如果是x
的2^n
,並2^n
多否則。由於直接相減是不允許的,我們必須否定的是(以二的補-n = ~n + 1
),所以我們發現
(~((!!result) << n)) + 1
仍然是0,如果result = 0
,並-2^n
否則,因此這是我們必須添加負x
。但是,對於正數x
,這也可以是非零值,因此在這種情況下我們必須使其無效,我們通過按位並使用mask
(對於x >= 0
爲0,並將所有位設置爲x < 0
)來做到這一點。
這看起來像我們在正確的軌道上,但仍然是不正確的: 當檢查,rempwr2(-2147483647,2)時,它應該給-3,當它應該給-3。 – 2013-04-27 19:18:57
Oooh,** right **,就是這樣。稍等片刻。 – 2013-04-27 19:20:28
@PDutt現在明白了,我很確定。 – 2013-04-27 19:31:38
那麼問題是什麼? – feralin 2013-04-27 18:53:43
檢查答案的程序是說這是不正確的: 「Test rempwr2(-2147483647 [0x80000001],1 [0x1])failed ... ...給出1 [0x1]。應爲-1 [ 0xffffffff]「 – 2013-04-27 18:56:37
它是否必須是便攜式的,或者我們可以假設二進制補碼和算術右移? – 2013-04-27 18:56:45