3

我的最后一个问题是我的家庭作业练习的最后一个问题。如果任何奇数位设置为 1,该函数应该返回 1。这是我到目前为止所拥有的:

int anyOddBit(int x) {
    return (x & 0xaaaaaaaa) != 0;
}

这工作得很好,但我不允许使用这么大的常数(只允许 0 到 255、0xFF)。我也不允许使用!=

具体来说,这是我仅限于使用的:

  Each "Expr" is an expression using ONLY the following:
  1. Integer constants 0 through 255 (0xFF), inclusive. You are
      not allowed to use big constants such as 0xffffffff.
  2. Function arguments and local variables (no global variables).
  3. Unary integer operations ! ~
  4. Binary integer operations & ^ | + << >>

我不知道如何在这些限制内做到这一点,如果有人能指出我正确的方向,我将不胜感激。提前致谢!

4

3 回答 3

4

您可以在 AND 之前执行 OR:

((x>>0) | (x>>8) | (x>>16) | (x>>24)) & 0xaa

最初的转变(x >> 0)将被优化 - 它在那里是为了保持一致的外观。

于 2012-04-23T01:02:21.337 回答
3

您可以使用:

!!((   ( x        & 0xff)
     | ((x >>  8) & 0xff)
     | ((x >> 16) & 0xff)
     | ((x >> 24) & 0xff)
) & 0xaa)

如果在任何源八位字节中设置了等效位,则将每个源八位字节 OR 在一起的“内部”位将为您提供一个八位字节,其中设置了每个位。因此,如果在源八位字节中设置了奇数位之一,它也将在目标八位字节中设置。

然后,通过简单地与 进行与0xaa,如果没有设置奇数位,您将获得一个零值,如果设置了任何奇数位,您将获得一个非零值。

然后,由于您需要 0 或 1,而您不能使用,因此您可以使用, 两个逻辑非运算符!=来实现类似的效果。!!它之所以有效,是因为!(any-non-zero-value)0!01


为了仅使用 12 个运算符(而不是按照我上面的原始解决方案的 13 个),您可以删除& 0xfffor>> 24值,因为它实际上不是必需的(零位从左侧移入):

!!((   ( x        & 0xff)
     | ((x >>  8) & 0xff)
     | ((x >> 16) & 0xff)
     | ((x >> 24)       )
) & 0xaa)

事实上,你可以做得更好。无论如何,最终& 0xaa将清除所有高 24 位,因此不需要任何& 0xff部分(它也适合一行):

!!((x | (x >> 8) | (x >> 16) | (x >> 24)) & 0xaa)

这使它减少到九个运营商。

于 2012-04-23T01:32:16.707 回答
1

0xaaaaaaaa基本上是(0xaa << 24) | (0xaa << 16) | (0xaa << 8) | (0xaa),这是允许的,不是吗?

于 2012-04-23T01:02:37.190 回答