用位运算符替换“==”

Posted

技术标签:

【中文标题】用位运算符替换“==”【英文标题】:Replacing "==" with bitwise operators 【发布时间】:2011-05-08 21:07:33 【问题描述】:

仅使用位运算符(|、&、~、^、>>、

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

【问题讨论】:

这主要是为了了解“==”的实际情况,以了解计算机如何在位级别上查看“==”,并查找类似的运算符是否可以在同样的时尚。 @Jens: "The homework tag...is now discouraged," 但是,@not_l33t,请(一如既往)遵循general guidelines:说明任何特殊限制,展示您迄今为止尝试过的内容,并询问具体是什么令人困惑你。 当你接近 int 的极限时有什么要求? IE。 INT_MAX,INT_MIN?还是只需要在更小的范围内工作? 我对编程还很陌生,问题更多的是要了解它是如何工作的。考虑到这一点,最好有一个无限的限制,尽管我开始发现这对我来说可能不太可能(按位操作有效,因为 32 位字符串)。 我想提醒任何试图使用按位运算作为性能提升的人,至少在 chrome 61 中,常规等于和按位等于方法之间几乎没有区别。 jsperf.com/bitwise-equal/1 【参考方案1】:

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

return !(x ^ y);

【讨论】:

您在这里将按位与逻辑运算符组合在一起,这可能会造成混淆。 它比公认的解决方案要好,因为根据定义 XOR 比 ADD 快(添加必须传输进位,所以它不是很可扩展)。 如果 x 和 y 都为零会怎样 @Kapil:嗯? 0 XOR 0 等于 0,就像 x 和 y 是任何其他相同的数字一样。【参考方案2】:

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

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

【讨论】:

虽然没有真正使用位运算符。 @Yada:但它使用“BASIC”运算符:) 我已经将这种方法与另一种方法(否定变量)结合使用。这样我就可以使用 + 代替,使其更接近计算机读取的内容。从而使其更快? int equal(int x, int y) return !((!x+1)+y); 如果x-y 的结果不能在int 中表示,这可能会调用未定义的行为【参考方案3】:

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

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

    为算术运算返回的条件代码(例如 x86 和 ARM 执行此操作)。在这种情况下,通常有一个“比较”指令,它减去两个值,不会写回整数寄存器,而是根据结果设置条件代码/标志。

    更多类似 RISC 的平台通常具有直接的“如果相等则分支”和“如果小于则分支”操作数,它们会根据结果进行比较和分支。基本相当于C代码

    if (a == b) goto label;
    

    if (a < b) goto label;
    

    全部在一条机器指令中。

【讨论】:

很好的例子!但为什么不使用“return t 据我了解,OP 不包括分支【参考方案4】:

此示例与减法相同,但更明确地说明了某些体系结构如何进行寄存器比较(我相信像 ARM)。

return !(1 + ~x + y);

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

因此,如果两个数字相等,您将得到-x + x =&gt; 0

(在寄存器级别上,! 运算符尚未完成,您只需测试条件代码或标志寄存器的“零位”,如果寄存器操作产生零结果,则会设置它,并且是否则清除。)

【讨论】:

【参考方案5】:

由于 XOR 与 (!=) 相同,因此 (x ^ y) 将仅在相等的值时返回 0。 我的看法如下,因为它是明智的,使用按位运算符并且可以工作。

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

【讨论】:

【参考方案6】:

我的看法

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

解释:如果x == y,则x &amp; ~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) );

【讨论】:

两个问题。 1) 这将检查 y 是否与 x 设置的所有位相同,不是 x == y。 2) 你正在使用==,即使它既不需要也不需要。 3) 只返回它而不是使用if 我知道是旧的,但是如果x 是负数会怎样?假设x = -1y = 0 那么if ( !( x &amp; ( ~( y + 1 )) ) ) 应该如何工作?如果x = -1y = -1 怎么样? `return x ^ y:` 应该可以工作。

以上是关于用位运算符替换“==”的主要内容,如果未能解决你的问题,请参考以下文章

编程思想:巧用位运算重构代码

用位运算实现四则运算之加减乘除(用位运算求一个数的1/3) via Hackbuteer1

java用位运算实现加减乘除

必用位运算

实部虚部合并和提取,巧用位运算符<<,>>, |,宏告警

用位运算实现两个数相加