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

2022-09-01 19:28:35

我需要多次检查两个整数是否在零的同一侧。我不在乎它是积极的还是消极的,只是因为它是同一面......性能非常重要。

目前我正在这样做:

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

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

基准测试列表:

  • 异或:带有错误修复的原始答案
  • 如果:显而易见的解决方案((&&)||(&&))
  • 位:@hatchet的解决方案(>>31) == (>>31)
  • BitAndXor:@greedybuddha的解决方案(0x80000000)
  • BitAndEquals:@greedybuddha的解决方案修改为不使用==^
  • 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是赢家


答案 1

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


答案 2
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
}

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


推荐