用位运算符替换“==”

时间:2010-11-12 04:38:17

标签: c binary bit-manipulation

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

int equal(int x, int y) {
    return x == y;
}

6 个答案:

答案 0 :(得分:63)

请注意,XORNOT EQUALS完全相同,XNOREQUALS完全相同。因此,以下内容将为您提供您想要的内容:

return !(x ^ y);

答案 1 :(得分:21)

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

int equal(int x, int y){
   return !(x-y);
}

答案 2 :(得分: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

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

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

    if (a == b) goto label;
    

    if (a < b) goto label;
    

    所有在一台机器指令中。

答案 3 :(得分:2)

这个例子与减法相同,但是更明确一些架构如何进行寄存器比较(比如ARM,我相信)。

return !(1 + ~x + y);

1表示进入ALU的进位位输入。一个数字x按位补充。取补码并加1会产生数字的二进制补码(x变为-x),然后将其添加到另一个数字以获得差异以确定相等。

因此,如果两个数字相等,则得到-x + x => 0

(在寄存器级别上,!运算符未完成,您只需测试条件代码或标志寄存器的“零位”,如果寄存器操作产生的结果为零,则会置位,而且很明显。)

答案 4 :(得分:1)

由于XOR与(!=)相同,因此(x ^ y)仅对相等的值返回0。 我的观点如下,因为它是明智的,使用逐位运算符和工作。

int notEqual(int x, int y){
        return (x ^ y);
}

答案 5 :(得分:-1)

我对此的看法

int equal(int x, int y){
   if((x & ~y) == 0)
       return 1;
   else
       return 0; 
}

说明:如果x == y,则x & ~y评估为0返回1,否则返回0为x!=y

Edit1: The above is equivalent to 

int equal(int x, int y){
    return !(x & ~y) ; // returns 1 if equal , 0 otherwise. 
}

上述代码在某些情况下失败,其中最高有效位变为1.解决方案是添加1.即正确的答案是

return !(x & (~y +1) );