用位运算符替换“==”
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】:请记住,XOR
与 NOT EQUALS
完全相同,XNOR
与 EQUALS
完全相同。因此,以下内容将为您提供您想要的:
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 => 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 & ~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 = -1
和y = 0
那么if ( !( x & ( ~( y + 1 )) ) )
应该如何工作?如果x = -1
和y = -1
怎么样? `return x ^ y:` 应该可以工作。以上是关于用位运算符替换“==”的主要内容,如果未能解决你的问题,请参考以下文章