【问题标题】:Return 1 if any bits in an integer equal 1 using bit operations in C如果使用 C 中的位运算,整数中的任何位等于 1,则返回 1
【发布时间】:2011-06-23 14:28:49
【问题描述】:

我已经考虑这个问题好几个小时了。这里是:

编写一个表达式,如果给定整数“x”有任何位等于 1,则返回 1。否则返回 0。

我知道我基本上只是想弄清楚 x == 0 是否因为这是唯一没有 1 位的 int,但我无法找到解决方案。您不能使用传统的控制结构。您可以使用按位运算符、加法、减法和位移。有什么建议吗?

【问题讨论】:

  • 这是任何大小的整数,还是你有一个已知的大小?
  • 加减法不是按位运算...
  • 如果其中一个答案解决了您的问题,您应该将其勾选为“已接受”。

标签: c bit-manipulation bitwise-operators


【解决方案1】:

使用 !!x 会给你正确的答案。因为 !0 = 1 和 !(任何非零数) = 0。

【讨论】:

  • 从 C 的角度来看这是最好的解决方案,但它不尊重任务的约束。
【解决方案2】:

这是我能想到的最好的:

y = (((-x) | x) >> (BITS - 1)) & 1;

其中 BITS = 32 表示 32 位整数,即 BITS = sizeof(int) * CHAR_BIT;

这是一个测试程序:

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

int main(int argc, char *argv[])
{
    const int BITS = sizeof(int) * CHAR_BIT;

    if (argc == 2)
    {
        int x = atoi(argv[1]);
        int y = (((-x) | x) >> (BITS - 1)) & 1;

        printf("%d -> %d\n", x, y);
    }

    return 0;
}

【讨论】:

  • 等等,(-x)|x 不总是 1??
  • 0 为 0 否则 MSB 位等于 1
  • -x &gt;&gt; (BITS - 1) 我认为效果很好。 | x 是不必要的,因为无论如何你都会移动这些位
  • -x 不适用于负数。 -x | x 设置 1 MSB 位,因为两个值之一是负数。
  • @Marlon:正如@ralu 所说,您需要确保如果 x 为负数,您仍然可以获得 MSB 集,因此需要 -x | x
【解决方案3】:

单独屏蔽每个位,将它们全部向下移动到 lsb 位置,或者将它们一起移动。

【讨论】:

  • 16 位的 16 种不同表达式?我认为有一个更优雅的解决方案。
【解决方案4】:

对于 32 位值,以下适用于所有位模式。

return (a | -a) >> 31;

【讨论】:

  • 确保移位是逻辑的,当然不是算术的——在 C 中使用无符号类型。
  • 还要注意解“return ~(x ^ x-1) >> 31;”以上,不适用于值 0x80000000。
  • 算术移位可以修改为-((a | -a) &gt;&gt; 31)
【解决方案5】:

您可以将您的 int 转换为 bool。但我怀疑这是你做作业的目的;-)

【讨论】:

  • bool 在标准 C(仅 C99)中不存在。
  • 是的,而且它内部很可能使用了分支逻辑,这违反了作业规则。但在一般情况下(如果语言支持),这是完成工作的一种简洁方式。
  • @Sven Marnach:我认为我会将 C99 称为“标准 C”,而将其他所有内容称为“过时的旧 C”。
【解决方案6】:
int any_bits_to_one(unsigned int n) {
  int result = 0, i;

  for (i=0; !result && i < sizeof(unsigned int) * 8; i++)
    result |= (n & (1<<i)) ? 1 : 0;

  return result;
}

【讨论】:

    【解决方案7】:

    对于 32 位整数

    int return_not_zero(int v)
    {
      r=v;
      r=(r&0xFFFF) | (r>>16); 
      r=(r&0xFF) | (r>>8);
      r=(r&0x0F) | (r>>4);
      r=(r&0x03) | (r>>2); 
      r=(r&0x01) | (r>>1); 
      return r;
    }
    

    【讨论】:

      【解决方案8】:

      !(x&&~x)&&x 怎么样?

      #include <stdio.h>
      void main(){
        int x;
        scanf("%d",&x);
        printf("%d\n",(!(x&&~x)&&x));
      }
      

      似乎可行,但我不确定何时发生溢出。

      【讨论】:

      • 如果允许&amp;&amp;,那么x &amp;&amp; 1 会简单一些
      【解决方案9】:

      0 || number - 仅当数字为 0 时返回 0,如果数字不是 0,则返回 1。由于没有任何位为 1 的数字将等于 0,因此我们需要用 0 来检查它。

      【讨论】:

      • || 是不允许的,因为它是一个逻辑运算符
      【解决方案10】:

      未经测试,这是我想到的第一件事:

       while(n & pow(2, e) == 0 && e++ <= 16) ;  // 16 or 32
      

      如果循环n后e == 16为0。

      【讨论】:

      • 您似乎在这里使用的不仅仅是按位运算?
      • pow(2, e)应该改成1 &lt;&lt; e,这样更快,也满足要求
      【解决方案11】:

      按位与 0 和任何数字都必须等于 0,但唯一万无一失的测试是使用 0xFFFF 或设置每个位。要设置所有位,您应该有一个带符号的 int,并将其分配为 -1。然后,无论大小如何,您都将拥有一个所有位都设置为 1 的 int。

      所以我的答案是按位与 -1 相加

      【讨论】:

        【解决方案12】:

        我相信这是最简单的方法。

        return !!(0|x);
        

        只有当所有位都为 0 或 x == 0 时,x 中才会有 1。所以 0|0 -> 0 否则 0|x -> 非零。

        【讨论】:

        • 很遗憾! 是不允许的逻辑运算符
        【解决方案13】:

        在 C 语言中,除零以外的任何值(正或负)都被视为 TRUE。并且应该有一个条件来检查您的问题的解决方案是否返回零或一(或零以外)。因此,这个答案完全符合您的要求。这仅使用按位运算符。

        return (x & 0xFFFF);
        

        当“x”中的任何一位都不为 1 时,此行返回零,而当“x”中的任何位为 1 时,此行返回非零(某种意义上的 TRUE)。

        【讨论】:

          猜你喜欢
          • 2015-12-27
          • 1970-01-01
          • 1970-01-01
          • 2019-03-18
          • 1970-01-01
          • 1970-01-01
          • 2018-03-27
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多