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

Posted

技术标签:

【中文标题】检查两个整数是不是在 0 的同一侧的最快方法【英文标题】:Fastest way to check if two integers are on the same side of 0检查两个整数是否在 0 的同一侧的最快方法 【发布时间】:2013-06-01 18:10:39 【问题描述】:

我需要多次检查两个整数是否在零的同一侧。我不在乎是正面的还是负面的,只要是同一面……而且表现很重要。

目前我正在这样做:

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

这比更明显的速度提高了 30%(使用 caliper 测试):

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

可以做得更快吗?

If anyone wants to see the test framework I'm using for the 30%, it's here. I used caliper 0.5-rc1

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

基准列表:

XOR:带有错误修复的原始答案 如果: 明显的((&amp;&amp;)||(&amp;&amp;)) 解决方案 Bits: @hatchet 的解决方案 (&gt;&gt;31) == (&gt;&gt;31) BitAndXor: @greedybuddha 的解决方案(0x80000000) BitAndEquals: @greedybuddha 的解决方案修改为使用== 而不是^ XorShift: @aaronman 的解决方案 (^)&gt;&gt;31 == 0

卡尺输出:

0% Scenariovm=java, trial=0, benchmark=XOR 1372.83 ns; ?=7.16 ns @ 3 trials
17% Scenariovm=java, trial=0, benchmark=Ifs 2397.32 ns; ?=16.81 ns @ 3 trials
33% Scenariovm=java, trial=0, benchmark=Bits 1311.75 ns; ?=3.04 ns @ 3 trials
50% Scenariovm=java, trial=0, benchmark=XorShift 1231.24 ns; ?=12.11 ns @ 5 trials
67% Scenariovm=java, trial=0, benchmark=BitAndXor 1446.60 ns; ?=2.28 ns @ 3 trials
83% Scenariovm=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) &lt; 0吗? (int1 ^ int2) &lt; 0 使用 2 个可以直接由硬件处理的操作。它不会比这更快。 我向你的精彩问题鞠躬,它应该被标记为“答案陷阱”。每个人都对这个问题进行了抨击,似乎被否决了。也许您的解决方案是唯一的? 这对 int1 == int2 有效吗? 【参考方案1】:

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

【讨论】:

我很确定这是最快的答案。除非有人想出更好的东西,否则我打算稍后再打勾。 那么应该有人给我一块饼干 我喜欢你的位移方式;) 为什么要转移? (int1 ^ int2) >= 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

两者的想法是相同的 - 除了符号位之外的所有内容,然后比较是否相等。我不确定哪个更快,右移 (>>) 或按位与 (&)。

【讨论】:

@durron597 - 我已经把按位和版本放回去了。 第二个答案和@greedybuddha 的答案一样,呃,不是,但是我已经把他改成了那个哈哈。大编辑即将到来。 无法将int 转换为bool,抱歉【参考方案3】:

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

【讨论】:

这个概念仍然存在,我不是 java 专家,但我相当确定你可以做类似的事情: (int1 & 0x8000000000000000L) ^ (int2 & 0x8000000000000000L) ,给出或接受语法问题和基于当然是你的整数大小。这里也提到了 - Best way to convert a signed integer to an unsigned long Java 中没有无符号整数 好的,所以除了选角之外,这与上面的建议有何不同?切换括号并说 (int1 ^ int2) & 0x8000000000000000 与 (int1 ^ int2) >> 31 完全相同。我称之为 dibs :)【参考方案4】:

其他答案

比较符号位

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

比较符号位的另一种方法

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

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

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

【讨论】:

但这只是 OP 的解决方案。 我认为应该快速且正确的替代答案。我现在看到 Ops 代码不是 好吧,应该是&lt;= 或者&gt; 0 -> 不同的一面优先 没错,但这会减慢速度,我的答案与您的基准相比如何? 我的我,相信更快,因为我只使用一次右移,而你使用两次,我改变了你的【参考方案5】:

另一个答案...

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

【讨论】:

【参考方案6】:
 int int1    = 3;
 int int2    = 4;
 boolean res = ( (int1 * int2) >= 0) ? true : false;

 System.out.println(res);

【讨论】:

这并不能解决问题,你需要知道它是哪一个 - 零或同侧 抛开性能不谈,这并不总是有效的。见http://ideone.com/2QkTyK 现在试试:int int1 = 1200000000; int int2 = 1500000000;

以上是关于检查两个整数是不是在 0 的同一侧的最快方法的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV - 检查两个图像是不是 100% 相同的最快方法

检查两个文件是不是相等的最快哈希算法是啥?

检查数字是不是有小数的最快方法[重复]

检查字节数组是不是全为零的最快方法

检查字符是不是为数字的最快方法?

检查范围内容差是不是相等的最快方法?