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

ybzsozfc  于 2021-06-30  发布在  Java
关注(0)|答案(6)|浏览(347)

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

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
注意:所有这些解决方案都检查第一位,基本上,对于零,它与正数相同。因此,如果这对您的应用程序有效,则不需要执行零检查。
基准清单:
xor:带有错误修复的原始答案
如果:很明显 ((&&)||(&&)) 解决方案
比特:@hatchet的解决方案 (>>31) == (>>31) 比坦德克索:@greedyforda的解决方案 (0x80000000) bitandequals:@greedyfoddha的解决方案修改为使用 == 不是 ^ 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是赢家

4uqofj5v

4uqofj5v1#

我会将它们位转换为无符号int,并对msb(最高有效位)进行异或运算—比任何比较(执行减法)或乘法都快得多

gg58donl

gg58donl2#

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
}

两者的思想是相同的-去掉所有符号位,然后比较是否相等。我不确定哪个更快,右移(>>)还是按位and(&)。

mjqavswn

mjqavswn3#

另一个答案。。。

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
}
pwuypxnk

pwuypxnk4#

备选答案
比较符号位

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

比较符号位的替代方法

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

我刚核实过,但op的代码错了 int1 == int2 . 如果以下内容相同,则它们将始终打印不同的内容。

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

b1payxdu5#

int int1    = 3;
 int int2    = 4;
 boolean res = ( (int1 * int2) >= 0) ? true : false;

 System.out.println(res);
uqdfh47h

uqdfh47h6#

(int1 ^ int2) >> 31 == 0 ? /*on same side*/ : /*different side*/ ; 这不一定能正确处理0,我不确定在这种情况下您想做什么。
edit:还想指出,如果这是用c而不是java实现的,那么可以通过去掉 == 0 因为布尔函数在c语言中的工作方式,所以情况会有所改变

相关问题