用位运算符替换"=="

not*_*33t 24 c binary bit-manipulation

仅使用按位运算符(|,&,〜,^,>>,<<)和其他基本运算符(如+, - 和!),是否可以替换下面的"=="?

int equal(int x, int y) {
    return x == y;
}
Run Code Online (Sandbox Code Playgroud)

Ign*_*ams 67

请记住,a XOR与a完全相同,NOT EQUALS并且XNOR完全相同EQUALS.因此,以下内容将为您提供您想要的内容:

return !(x ^ y);
Run Code Online (Sandbox Code Playgroud)

  • 它比公认的解决方案更好,因为根据定义,XOR比ADD更快(添加必须传输进位,所以它不是很可扩展). (9认同)
  • 您在这里将按位与逻辑运算符相结合,这可能会令人困惑。 (2认同)

sth*_*sth 22

如果它们之间没有差异,则两个数字相等:

int equal(int x, int y){
   return !(x-y);
}
Run Code Online (Sandbox Code Playgroud)

  • 虽然没有真正使用按位运算符. (6认同)
  • 如果`xy`的结果无法在`int`中表示,则可能会调用未定义的行为 (4认同)

Fab*_*sen 14

C !运算符实际上只是简写!= 0,所以使用它似乎非常接近欺骗:)

这是我使用按位运算的假设,假设32位二进制补码机具有算术右移(技术上,在C算术右移是未定义的,但我在双补码机上看到的每个C编译器都支持这一点):

int t = (x - y) | (y - x); // <0 iff x != y, 0 otherwise
t >>= 31; // -1 iff x != y, 0 otherwise
return 1 + t; // 0 iff x != y, 1 otherwise
Run Code Online (Sandbox Code Playgroud)

也就是说,实际的编译器没有这个问题.真正的硬件实际上直接支持比较.细节取决于架构,但有两个基本模型:

  1. 为算术运算返回的条件代码(例如x86和ARM执行此操作).在这种情况下,通常会有一个"比较"指令,它减去两个值,不会写回整数寄存器,而是根据结果设置条件代码/标志.
  2. 更多类似RISC的平台通常具有直接"分支如果相等"和"分支如果小于"操作数,它们根据结果进行比较和分支.它基本上等同于C代码

    if (a == b) goto label;
    
    Run Code Online (Sandbox Code Playgroud)

    要么

    if (a < b) goto label;
    
    Run Code Online (Sandbox Code Playgroud)

    一体机指令.