检查两个整数是否在0的同一侧的最快方法

我需要检查两个整数是否在零的同一侧多次。 我不在乎它是积极的还是消极的,只是它是同一面……而且表现非常重要。

目前我这样做:

if (int1 == 0 || int2 == 0) { // handle zero } else if ((int1 ^ int2) > 0) { // different side } else { // same side } 

这比速度提高30%(用卡尺测试)更明显:

 if ((int1 > 0 && int2 > 0) || (int1 < 0 && int2 < 0)) { 

可以更快地完成吗?

如果有人想看到我用于30%的测试框架,它就在这里。 我使用了卡尺0.5-rc1

注意:所有这些解决方案都检查第一位,基本上,零与正数相同。 因此,如果它适用于您的应用程序,则无需进行零检查。

基准清单:

  • 异或:错误修正的原始答案
  • Ifs:明显((&&)||(&&))解决方案
  • 位: @ hatchet的解决方案(>>31) == (>>31)
  • BitAndXor: @ greedybuddha的解决方案(0x80000000)
  • BitAndEquals: @ greedybuddha的解决方案被修改为使用== not ^
  • XorShift: @ aaronman的解决方案(^)>>31 == 0

卡尺输出:

 0% Scenario{vm=java, trial=0, benchmark=XOR} 1372.83 ns; ?=7.16 ns @ 3 trials 17% Scenario{vm=java, trial=0, benchmark=Ifs} 2397.32 ns; ?=16.81 ns @ 3 trials 33% Scenario{vm=java, trial=0, benchmark=Bits} 1311.75 ns; ?=3.04 ns @ 3 trials 50% Scenario{vm=java, trial=0, benchmark=XorShift} 1231.24 ns; ?=12.11 ns @ 5 trials 67% Scenario{vm=java, trial=0, benchmark=BitAndXor} 1446.60 ns; ?=2.28 ns @ 3 trials 83% Scenario{vm=java, trial=0, benchmark=BitAndEquals} 1492.37 ns; ?=14.62 ns @ 3 trials benchmark us linear runtime XOR 1.37 ================= Ifs 2.40 ============================== Bits 1.31 ================ XorShift 1.23 =============== BitAndXor 1.45 ================== BitAndEquals 1.49 ================== vm: java trial: 0 

看起来@aaronman是赢家

(int1 ^ int2) >> 31 == 0 ? /*on same side*/ : /*different side*/ ; 这不一定正确处理0我不确定在这种情况下你想做什么。
编辑:还想指出,如果这是在c而不是java,它可以通过摆脱== 0进一步优化,因为布尔在c中的工作方式,案件将切换虽然

 if (int1 == 0 || int2 == 0) { // handle zero } else if ((int1 >> 31) == (int2 >> 31)) { // same side } else { // different side } 

要么

 if (int1 == 0 || int2 == 0) { // handle zero } else if ((int1 & Integer.MIN_VALUE) == (int2 & Integer.MIN_VALUE)) { // same side } else { // different side } 

两者的想法是相同的 – 剥离除了符号位之外的所有内容,然后将其进行比较以获得相等性。 我不确定哪个更快,右移(>>)或按位和(&)。

我会把它们变成unsigned int,而xor是MSB(最重要的位) – 比任何比较(减法)或乘法快得多

替代答案

比较符号位

 return ((n >> 31) ^ (n2 >> 31) ) == 0 ? /* same */ : /* different */; 

比较符号位的替代方式

 return (((int1 & 0x80000000) ^ (int2 & 0x80000000))) == 0 ? /* same */ : /* different */; 

我刚刚validation过,但是当int1 == int2时,Op的代码是错误的。 如果它们相同,则以下将始终打印不同。

 if (int1 == 0 || int2 == 0) { // handle zero } else if ((int1 ^ int2) < 0) { // same side } else { // different side } 

另一个答案……

 final int i = int1 ^ int2; if (i == 0 && int1 == 0) { // both are zero } else if (i & Integer.MIN_VALUE == Integer.MIN_VALUE) { // signs differ } else { // same sign } 
  int int1 = 3; int int2 = 4; boolean res = ( (int1 * int2) >= 0) ? true : false; System.out.println(res);