澄清一点点陈述

时间:2015-01-16 15:45:11

标签: c bitwise-operators

如果(a&(a-1)/ 2)在C中意味着以下条件是什么?

#include <stdio.h>

int main()
{
   int a;
   scanf("%d", &a);

   if(a & (a-1)/2)
   {
      printf("Yes\n");
   }
   else{
       printf("No\n");
   }
   return 0;
}

我在这里没有得到/运营商的意思。除法运算符在条件中意味着什么?

5 个答案:

答案 0 :(得分:3)

除法运算符/只是将左侧划分为右侧。在这种情况下,右侧是2,所以它将a-1右移一位(算术移位,对整数进行符号扩展)。

因此,整个表达式计算 - a>=0 - a((a-1)>>1)是否都设置了相同的位(在这种情况下&将产生非零值)。对于a<0,请在最后看到评论。

这是一些测试代码:

#include <stdio.h>
#include <stdlib.h>

int
main (int argc, char **argv)
{
  int i;
  for (i = 0; i < 256; i++)
    {
      printf ("%3d %s\n", i, (i & (i - 1) / 2) ? "yes" : "no");
    }
  exit (0);
}

给出了

  0 no
  1 no
  2 no
  3 yes
  4 no
  5 no
  6 yes
  7 yes
  8 no
  9 no
 10 no
 11 yes
 12 yes
 13 yes
 14 yes
 15 yes
 16 no
 17 no
 18 no
 19 yes
 20 no
 21 no
 22 yes
 23 yes
 24 yes
 25 yes
 26 yes
 27 yes
 28 yes
 29 yes
 30 yes
 31 yes
 32 no
 33 no
 34 no
 ... abbreviated for clarity ...

这会检测以下数字:

  • 有两个或多个相邻的二进制1或;

  • 是否定的,但不是MININT

以下是:

  • 如果a>=0,则(a-1)/2 == a/2(因为舍入始终为零)。因此,这对于a>=0}到a & (a>>1)是等效的,如果a中的任何位右边的位被设置,即如果存在两个或更多个相邻的位,那么它将是1。

  • 如果a<0a!=MININT(并因此1作为其MSB),则(a-1)也必须为负且小于{{1} },因此-1也必须为负(因此(a-1)/2为MSB),在这种情况下1为非零,因为其MSB也必须为1.

  • 如果a & ((a-1)/2)),则a==MININTa-1,因此(a-1)/ 2没有位均为1。

答案 1 :(得分:2)

对于非负值,除以2相当于将其向右移1位。对于负值,它不是等价的,但我怀疑代码的作者并不打算使用负值。

(请注意,这种非等价与外来非2&s补码架构或算术筛选无关。在C和C ++语言中,签名除法需要向0舍入,这使得无法实现通过对2的补码架构的负值进行简单的移位来划分除法。需要进行移位后校正。)

现在,关于整个a & (a - 1) / 2表达式正在做什么......让我们仅限制对非负值的考虑。

减1相当于反转数字中的所有尾随0位,然后反转最后一个(最低有效)1位。除以2相当于向右移1位。

&操作的上下文中,整个事情等同于:在a中删除最后1位,将整个事物向右移1位,并将&与原始价值。

在这种情况下,我没有看到杀死最后1位的重点。对于正值,整个事物看起来等同于a & (a / 2)(即a & (a >> 1))),它只检测原始a中是否有两个相邻的1位。

答案 2 :(得分:0)

它从1中减去1,然后除以2,然后进行比特操作。

答案 3 :(得分:0)

/条件下,运算符只进行除法。唯一重要的是条件的结果是0(假)还是0(真)。

作为程序实际执行的内容,它看起来与二进制数学有关,所以你应该问一个了解更多相关信息的人。

答案 4 :(得分:-1)

在表达式a&amp; (a - 1)/ 2有一个按位运算符和一个除法运算符。将它们一起使用是非常不寻常的。因此,我不知道优先级是什么(它将a-1除以2并且按位并且使用a,或者它是按位还是a和a-1,然后将结果除以2)。我实际上并不关心优先级是什么,因为我不知道程序员编写代码的假设是什么优先级。

如果您看到这样的代码,您需要找出它的作用,您需要找出它的目的,如果两者相同,您添加括号以使意图清晰,如果它们不是同样你发现了一个错误,并弄清楚它如何影响程序以及如何处理它。