【问题标题】:Implementing logical negation with only bitwise operators (except !)仅使用按位运算符实现逻辑否定(除了!)
【发布时间】:2011-01-21 23:34:31
【问题描述】:

~ & ^ | + << >> 是我唯一可以使用的操作

在我继续之前,这是一个家庭作业问题,我已经坚持了很长时间。

我最初的方法:我认为 !x 可以用二进制补码来完成,并用它的加法逆来做一些事情。我知道这里可能有一个异或,但我真的不知道如何处理这个问题。

声明:我也不能使用条件、循环、== 等,只能使用我上面提到的函数(按位)。

例如:

!0 = 1
!1 = 0
!anything besides 0 = 0

【问题讨论】:

  • 您真的希望他们直接评估为 1 和 0,还是只是逻辑真假?即~0 是否可以接受为逻辑真?
  • 注意:+ 不是位运算符。
  • 这种练习本质上是没有意义的,因为任何使用结果都需要一个基本上与零进行比较的条件。我的答案是if (var); else { /* your code here */ }
  • @R.:诀窍是你不需要使用条件,因为 C 没有bool。 (例如,而不是return x != 0;,你可以说return x;,假设他不需要1返回......这就是我想要弄清楚的。)
  • @Mehrdad:C99 确实有 bool,但 AFAIK 你必须包含 stdbool.h 才能得到它,除非你很高兴说 _Bool

标签: c bit-manipulation boolean-logic negation


【解决方案1】:

假设一个 32 位无符号整数:

(((x>>1) | (x&1)) + ~0U) >> 31

应该做的伎俩

【讨论】:

  • 不错。将除 0 以外的所有数字转换为“正数”,然后减去 1,即只有 0 为负数,然后提取符号位。
  • 这可以简化为(~(x >> 1) + x) >> 31
【解决方案2】:

假设x是有符号的,需要返回0代表任何不为零的数字,1代表零。

在大多数实现中,有符号整数的右移通常是算术移位(例如,符号位被复制)。因此,将x 右移 31 并将其否定 31。这两个中的一个将是负数,因此右移 31 将是 0xFFFFFFFF (当然,如果 x = 0 那么右移将产生 0x0 这就是你想)。你不知道 x 或其否定是否是负数,所以只需将它们“或”在一起,你就会得到你想要的。接下来加 1 和你的好。

实现:

int bang(int x) {
    return ((x >> 31) | ((~x + 1) >> 31)) + 1;
}

【讨论】:

  • 我认为你应该否定而不是添加一个。即~((x >> 31) | ((~x + 1) >> 31)).
  • 其实,没有。添加1是正确的。我忘记了>> 移位是 C 中的算术,而不是逻辑。因此,>> 31-ing 10...00 将产生 11...11,而不是 00...01
【解决方案3】:

以下代码将任意 1 位复制到所有位置。这会将所有非零值映射到0xFFFFFFFF == -1,同时将0 留在0。然后加1,将-1映射到0,将0映射到1

x = x | x << 1  | x >> 1
x = x | x << 2  | x >> 2
x = x | x << 4  | x >> 4
x = x | x << 8  | x >> 8
x = x | x << 16 | x >> 16

x = x + 1

【讨论】:

  • 你可以用~x代替x + 1
  • @Chris Lutz:将 0 映射到 -1,而不是所需的 1。
【解决方案4】:

对于 32 位有符号整数 x

// Set the bottom bit if any bit set.
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;

x ^= 1;   // Toggle the bottom bit - now 0 if any bit set.
x &= 1;   // Clear the unwanted bits to leave 0 or 1.

【讨论】:

    【解决方案5】:

    假设例如一个 8 位无符号类型:

    ~(((x >> 0) & 1)
    | ((x >> 1) & 1) 
    | ((x >> 2) & 1)
    ...
    | ((x >> 7) & 1)) & 1
    

    【讨论】:

    • @Jay - 像*(unsigned *)&amp;i这样的演员
    【解决方案6】:

    你可以只做 ~x & 1 因为它为 0 产生 1,为其他所有东西产生 0

    【讨论】:

    • ~0x0002 = 0xFFFD, 0xFFFD & 1 = 1
    猜你喜欢
    • 2020-01-23
    • 1970-01-01
    • 2011-07-14
    • 2015-07-17
    • 1970-01-01
    • 1970-01-01
    • 2012-07-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多