我有以下任务:
使用位移计算
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。为什么呢?
答案 0 :(得分:6)
密切关注舍入行为。
/
(整数除法)总是向零舍入。答案 1 :(得分:6)
在我自己寻找一个好的答案之后,我偶然发现了这个并且能够得到一个工作片段。让我帮助向将来可能会发现这一点的其他人解释这一点。
(x + ((x >> 31) & ((1 << n) + ~0))) >> n
这段代码是Sotelo发布的您正在寻找的代码。它起作用的原因非常重要,特别是对于你理解你的作业。首先,你必须完全理解2的补码表示。这是当最高有效位用于将整个二进制表示偏移相应的2的幂时。 如果我们仅对32位(大多数处理器中的标准)成像,那么我们可以使用右移(&gt;&gt;)将最高有效位移动到最低有效位。在这样做时,您将执行算术右移,它将在整个位级表示中复制最高有效位(如果它为负,则为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可分数的幂。然后最后将你的权力转移给你两个。
答案 2 :(得分:5)
由于二进制补码表示,负数在二进制表示中是一次性的。也许阅读two's complement会有所帮助。
答案 3 :(得分:4)
public int DivideByPowerOf2(int x, int n)
{
return (x + ((x >> 31) & ((1 << n) + ~0))) >> n;
}