使用位移除以2的幂
我有以下任务:
使用位移计算
x/(2^n)
,0 <= n <= 30
。要求:向零舍入。
例子:
divpwr2(15,1) = 7 divpwr2(-33,4) = -2
合法经营者:
! ~ & ^ | + <>
! ~ & ^ | + <>
最大运营商数量:15
这是我到目前为止所得到的:
public int DivideByPowerOf2(int x, int n) { //TODO: find out why DivideByPowerOf2(-33,4) = -3 instead of -2 return x >> n; }
DivideByPowerOf2(15,1) = 7
就可以了。
但是DivideByPowerOf2(-33,4) = -3
而不是-2。 为什么?
在找到一个好的答案之后,我偶然发现了这个并且能够获得一个工作片段。 让我帮助向将来可能会发现这一点的其他人解释这一点。
(x + ((x >> 31) & ((1 << n) + ~0))) >> n
Sotelo发布的代码片段就是您所寻找的代码片段。 它起作用的原因非常重要,特别是对于你理解你的作业。 首先,您必须完全理解2的补码表示。 这是当最高有效位用于将整个二进制表示偏移相应的2的幂时。如果我们只对32位(大多数处理器中的标准)成像,那么我们可以使用右移(>>)来移动最重要的位到最低位。 在这样做时,您将执行算术右移,它将在整个位级表示中复制最高有效位(如果它为负,则为1)。 在6位二进制表示中,这将导致任一个
000000 111111
然后,这允许我们进一步操作整数以确定一些属性。 首先,我们需要找到2的幂,我们将除以(在这种情况下为n)并将二进制移到该位置,然后减去1.例如,让我们使用3或8的幂。
(000001 << 3) -1 000111
现在我们将这两个二进制表示我们将和它们在一起
111111 & 000111 = 000111 (case 1) 000000 & 000111 = 000000 (case 2)
现在假设x是奇数或偶数(分别为情况1和情况2),我们可以将x添加到此并获得一个2的完美幂的数字(如果我们除以2的幂,我们将获得正确的答案)。 下面是一些例子,分别为x = 8,10,-8,-12。
001000 + 000000 = 001000 001010 + 000000 = 001010 now for the negatives that plague you 111000 + 000111 = 111111 110100 + 000111 = 111011
现在最后一步是将这些数字除以n的幂。 为了除以8,如上所述,则为3。
001000 >> 3 = 000001 or 1 in decimal (8/8 = 1) 001010 >> 3 = 000001 or 1 in decimal (10/8 = 1 because of truncation) 111111 >> 3 = 111111 or -1 in decimal (-8/8 = -1) 111011 >> 3 = 111111 or -1 in decimal (-12/8 = -1 because of truncation)
所以你有它。 你的第一个任务是找出它是负数还是正数,然后从负数中获得与你的2 -1的幂相对应的位。 将其添加到x以获得二进制2的可分数的幂。 然后最后分给你两个权力的右移。
密切关注舍入行为。
-
/
(整数除法)总是向零舍入。 - 位移有什么作用?
- 你怎么能弥补这种差异?
由于二进制补码表示,负数在二进制表示中是一次性的。 也许阅读两个补语会有所帮助。
public int DivideByPowerOf2(int x, int n) { return (x + ((x >> 31) & ((1 << n) + ~0))) >> n; }