【问题标题】:Bitwise Remainder Operator位余数运算符
【发布时间】:2013-04-27 18:52:29
【问题描述】:

我一直在搞乱我在互联网上发现的按位运算符问题,并找到了一个完全让我难过的问题。

int rpwr2(int x, int n)
{
   //Legal ops: ! ~ ^ | + << >>

   //My attempt at a solution:
   int power = (1 << n) + ~0;
   return x & power;
}

【问题讨论】:

  • 那么问题是什么?
  • 检查答案的程序说它不正确:“Test rempwr2(-2147483647[0x80000001], 1[0x1]) failed... ... 给出 1[0x1]。应该是 -1[0xffffffff]"
  • 它必须是可移植的,还是我们可以假设二进制补码和算术右移?
  • int mask = x &gt;&gt; 31; return (result + mask) ^ mask; 有条件地否定结果显然不可移植。
  • 这些问题仅针对 Intel 32 位架构构建。我们可以假设二进制补码和算术右移。

标签: c bit-manipulation operator-keyword


【解决方案1】:

haroldsuggestion 几乎是正确的,但是对于否定的x 而不是-result,我们需要

result - (1 << n)

除非结果为 0。在二进制补码中,

x & ((1 << n) - 1)

对于每个x 都与x2^n 一致(并且n 小到足以使1 &lt;&lt; n 正常工作)。那就是x在区间[0, 2^n)中的残差类的代表。

要求是获得负数x 的负数(更准确地说是非正数)余数(在区间 (-2^n, 0] 内)。这意味着,对于不是2^n 倍数的负x,我们必须从x &amp; ((1 &lt;&lt; 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 &gt;= 0,那么mask = 0(x &amp; power) + (whatever &amp; mask) = (x &amp; power) 是正确的结果。

对于x &lt; 0,我们必须减去1 &lt;&lt; n,除非result = 0

(!!result) << n
如果x2^n 的倍数,则

为0,否则为2^n。由于不允许直接减法,我们必须否定它(-n = ~n + 1 在二进制补码中),所以我们找到

(~((!!result) << n)) + 1

如果result = 0 仍然为0,否则-2^n,因此这是我们必须为负x 添加的内容。但这也可以是正值x 的非零值,因此在这种情况下我们必须将其无效,我们通过按位和mask(对于x &gt;= 0 为 0 并设置所有位)来实现为x &lt; 0)。

【讨论】:

  • 这似乎我们在正确的轨道上,但仍然不正确:检查时,rempwr2(-2147483647, 2),它给出了 -1,而它应该给出 -3。
  • @PDutt 现在知道了,我很确定。
  • @harold 是的,你是对的。我被错误的结果激怒了,但是我们不需要-(x &amp; power) 来表示负数x,而是(x &amp; power) - (1 &lt;&lt; n),除非余数为0。
  • 成功了!你能更详细地解释一下return语句吗?您提出这个解决方案的想法是什么?
  • @PDutt 我稍微扩展了解释。这样说清楚了吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多