在Java中检测偶数的最有效方法是什么? [英] What is the most efficient way to detect even numbers in Java?

查看:71
本文介绍了在Java中检测偶数的最有效方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

确定数字甚至使用Java的最有效方法是什么?为什么?

What would be the most efficient manner to determine that a number is even using Java, and why?

会使用模数或减法,还是我实际上没有想到的其他方式?

Would it be using modulo or subtraction, or some other manner that I haven't actually thought of?

一个人想象我可以通过一个简单的测试类来确定这一点-我可以-但这真的不能解释为什么,会吗?

One imagines I could determine this doing a simple test class - and I can - but that really wouldn't explain why, would it?

我并没有为提高处理 许多项目的崇高目标而做一些疯狂的裤子性能调整.但是我很好奇,是否应该将一种方法 优先于另一种方法,并将其作为常规做法.同样,我们不会使用&代替&&,为什么在可以使用&时为什么使用%?

I'm not doing some crazy-pants performance tuning for some lofty goal of processing that many items faster. But I was curious if one method should be preferred over the other as common practice. In the same way we wouldn't use & in place of &&, why use % when we can use &?

推荐答案

如果检查以下两种方法的热点7生成的程序集:

If you check the assembly generated by hotspot 7 of these two methods:

public static boolean isEvenBit(int i) {
    return (i & 1) == 0;
}
public static boolean isEvenMod(int i) {
    return i % 2 == 0;
}

您将看到,虽然mod进行了优化,并且基本上按位执行了and,但是由于两个操作并非严格等效,因此它具有一些额外的说明*.其他JVM可能会对其进行不同的优化.该程序集发布在下面以供参考.

you will see that although the mod is optimised and basically does a bitwise and but it has a few extra instructions because the two operations are not strictly equivalent*. Other JVMs might optimise it differently. The assembly is posted below for reference.

我还运行了一个微基准测试,它证实了我们的观察结果:isEventBit稍快一些(但是两者都运行大约2个纳秒,因此整个典型程序可能不会受到太大影响) ):

I also ran a micro benchmark which confirms our observation: isEventBit is marginally faster (but both run in about 2 nanoseconds so probably won't have much of an inmpact on a typical program as a whole):

Benchmark                     Mode  Samples  Score   Error  Units
c.a.p.SO16969220.isEvenBit    avgt       10  1.869 ± 0.069  ns/op
c.a.p.SO16969220.isEvenMod    avgt       10  2.554 ± 0.142  ns/op


isEvenBit

  # {method} 'isEvenBit' '(I)Z' in 'javaapplication4/Test1'
  # parm0:    rdx       = int
  #           [sp+0x20]  (sp of caller)
  0x00000000026c2580: sub    rsp,0x18
  0x00000000026c2587: mov    QWORD PTR [rsp+0x10],rbp  ;*synchronization entry
                                                ; - javaapplication4.Test1::isEvenBit@-1 (line 66)
  0x00000000026c258c: and    edx,0x1
  0x00000000026c258f: mov    eax,edx
  0x00000000026c2591: xor    eax,0x1            ;*ireturn
                                                ; - javaapplication4.Test1::isEvenBit@11 (line 66)
  0x00000000026c2594: add    rsp,0x10
  0x00000000026c2598: pop    rbp
  0x00000000026c2599: test   DWORD PTR [rip+0xfffffffffdb6da61],eax        # 0x0000000000230000
                                                ;   {poll_return}
  0x00000000026c259f: ret    

isEvenMod

  # {method} 'isEvenMod' '(I)Z' in 'javaapplication4/Test1'
  # parm0:    rdx       = int
  #           [sp+0x20]  (sp of caller)
  0x00000000026c2780: sub    rsp,0x18
  0x00000000026c2787: mov    QWORD PTR [rsp+0x10],rbp  ;*synchronization entry
                                                ; - javaapplication4.Test1::isEvenMod@-1 (line 63)
  0x00000000026c278c: mov    r10d,edx
  0x00000000026c278f: and    r10d,0x1           ;*irem
                                                ; - javaapplication4.Test1::isEvenMod@2 (line 63)
  0x00000000026c2793: mov    r11d,r10d
  0x00000000026c2796: neg    r11d
  0x00000000026c2799: test   edx,edx
  0x00000000026c279b: cmovl  r10d,r11d
  0x00000000026c279f: test   r10d,r10d
  0x00000000026c27a2: setne  al
  0x00000000026c27a5: movzx  eax,al
  0x00000000026c27a8: xor    eax,0x1            ;*ireturn
                                                ; - javaapplication4.Test1::isEvenMod@11 (line 63)
  0x00000000026c27ab: add    rsp,0x10
  0x00000000026c27af: pop    rbp
  0x00000000026c27b0: test   DWORD PTR [rip+0xfffffffffdb6d84a],eax        # 0x0000000000230000
                                                ;   {poll_return}
  0x00000000026c27b6: ret    

正如注释中指出的,

*,%并不是真正的模.这是剩余的.所以(i % 2) != (i & 1)如果i < 0. isEvenMod代码中的额外指令将结果的符号设置为i的符号(然后将其与零进行比较,这样就浪费了精力).

* as pointed out in the comments, % isn't really modulo; it's the remainder. So (i % 2) != (i & 1) if i < 0. The extra instructions in the isEvenMod code sets the sign of the result to the sign of i (and then just compares it to zero, so the effort is wasted).

这篇关于在Java中检测偶数的最有效方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆