【问题标题】:Fastest Two Number Sign Comparison Including Zero最快的两个数字符号比较,包括零
【发布时间】:2017-02-07 21:40:22
【问题描述】:

考虑到符号可以是正数、负数或零,找到两个数字是否具有相同符号的最快方法是什么。

通常,您可以这样说两个数字具有相同的符号:

Math.signum(int1) == Math.signum(int2);

你可以使用这个来优化它:

int1 ^ int2 >= 0;

但是,这是假设零是正数。有哪些方法会返回 true,包括零。

一些错误示例如下:

a = 0; b = 1;
boolean test = a ^ b >= 0

测试会产生真而不是假。

我运行了一些测试平台,发现按位函数返回值的速度快了近 4 个数量级。由于这是我将在一个非常大的树中为每个节点使用的函数,因此我需要尽可能地优化它。

我会发布一个尝试过的解决方案,但我找不到比原来的解决方案更好的解决方案。

编辑:我意识到这里发现了一个类似的问题:Fastest way to check if two integers are on the same side of 0 我在问是否有办法找出符号是否相同,包括零。所以 1 和 1 之间的比较为真,-1 和 -1 为真,0 和 0 为真,0 和 1 为假,0 和 -1 为假,等等。这与上面提出的问题不同!

【问题讨论】:

  • 放手吧。你不能对效率感兴趣而选择用java开发。为提高效率,请选择汇编语言、c 或(可能)fortran 之类的语言
  • 这是我上面链接的问题的答案:(int1 ^ int2) >> 31 == 0 ? /*on same side*/ : /*different side*/
  • @Andremoniy 我已经检查了这个解决方案。这不处理我在标题中提到的为零的情况。
  • @DwB,我们已经不是 1996 年了。

标签: java bit-manipulation sign zero


【解决方案1】:

这是我想出的:

private static boolean signcmp(int x, int y) {
    return ((( x >> 31) | (-x >>> 31)) ^ (( y >> 31) | (-y >>> 31))) == 0; 
}

【讨论】:

  • (a ^ b) == 0a == b 是一回事,我希望 JIT 编译器也知道这一点,但它可能还是更好的 idk
  • 我必须说我真的很惊讶差异如此之大,它们实际上只是彼此的小变种。 OR vs SUB,SHR vs SAR,应该没关系
  • @harold 可能是因为您提供了部分解决方案,而我没有很好地实现它。我能看到的最大区别是 OR 与 SUB。他们真的需要同样的时间吗?
  • @MichaelChoi 他们在我知道的任何机器上都同样快,在硬件上或者当然更快,但你不是在这里写 VHDL。也许你的时间不可靠?例如,如果切换基准测试的顺序会有所不同,您可以尝试。
  • @harold 是的,我只是尝试切换结果不一致的顺序。我还不是很擅长编码,所以我认为我的测试台没有那么准确。单独运行它们会产生几乎相同的结果,我假设偏差只是后台任务的结果。
【解决方案2】:

您可以使用signum 的整数版本,例如(未测试):

int signum(int x) {
    int m = x >> 31;
    int neg_m = -x >> 31;
    return m - neg_m;
}

这里m 将为 -1 iff x < 0(否则为 0),neg_m 将为 -1 iff x > 0(忽略 Integer.MIN_VALUE)。他们的区别是,

  • -1,对于 x
  • 0,对于 x == 0
  • 1,对于 x > 0

它还为Integer.MIN_VALUE 提供了 0,但因为在您的情况下不会发生这种情况,所以这无关紧要。

【讨论】:

  • 类似的答案可以在@Matthew_McPeak 找到,因为更清晰,所以选择这个作为答案。
  • 另外,我相信我的答案适用于Integer.MIN_VALUE,因为在负值上使用了无符号右移,而不是对 OP 很重要。
  • @MatthewMcPeak 感谢 OR 逻辑,我想说,但这是由无符号移位启用的,所以它有点回到那个.. 例如,无符号移位和加法将完全等效我想出了什么
【解决方案3】:

如果没有对此进行基准测试,我怀疑您是否可以做得更好

sameSign = a < 0 ? b < 0 : ( a == 0 ) == ( b == 0 );

【讨论】:

  • 我运行了一个测试台,它看起来比@harold 的解决方案运行得慢。感谢您的意见。
  • 好的,很公平。感谢您的检查。您可能会发现它依赖于硬件,但我对此表示怀疑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-19
  • 1970-01-01
  • 1970-01-01
  • 2012-03-15
  • 1970-01-01
  • 2015-11-28
相关资源
最近更新 更多