java - 如何有效地只生成奇数(或偶数)随机数?

标签 java optimization random

通过查看有关偶数或奇数生成的其他问题,我很好奇哪种方法最有效(就速度而言)。

例如,假设我想生成许多从 1(含)到 1000(不含)的奇数;对于每次迭代,我通常使用的方法如下:

  • 生成一个介于 0(含)和 500(不含)之间的随机数
  • 乘以2
  • 添加1

有没有更好的方法?

最佳答案

我今天偶然发现了这个方法,但我在 StackOverflow 上找不到任何用于仅生成偶数或奇数的方法。

此方法利用了以下事实:在二进制中,所有偶数(包括 0)都将其最低有效位设置为 0。而所有奇数的最低有效位都设置为 1 .

因此,要生成一个奇数,我们可以简单地生成一个在所需范围内的随机数,然后用1按位或它。 :

ThreadLocalRandom.current().nextInt(0, 1_000) | 1

使用这种方法,如果生成器选择了一个奇数,那么它就不管了。但是,如果选择了偶数,则将其与 1 进行按位或运算。本质上是增加它。

同样,生成 2 之间的偶数(含)和1000 (独占),那么我们只需要清除最低有效位。为此,我们可以简单地按位与 -2 的值:

ThreadLocalRandom.current().nextInt(2, 1_000) & -2

使用这种方法,如果生成器选择了一个偶数,那么它就不管了。但是,如果选择了奇数,则将其与 -2 进行按位运算。本质上是递减它。

这些方法对负值非常有效,long

这是一个 JMH 基准测试,比较了在 1 之间生成奇数的两种方法。 (含)和1000 (独家):

@State(Scope.Benchmark)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@Measurement(iterations = 20, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@Fork(5)
public class MyBenchmark {

    private static final ThreadLocalRandom RANDOM = ThreadLocalRandom.current();

    public static void main(String[] args) throws Exception {
        org.openjdk.jmh.Main.main(args);
    }

    @Benchmark
    public int oldMethod() {
        return RANDOM.nextInt(0, 500) * 2 + 1;
    }

    @Benchmark
    public int newMethod() {
        return RANDOM.nextInt(0, 1000) | 1;
    }
}

结果:

Benchmark              Mode  Cnt  Score   Error  Units
MyBenchmark.newMethod  avgt  100  6.079 ± 0.137  ns/op
MyBenchmark.oldMethod  avgt  100  6.325 ± 0.009  ns/op

oldMethod可以通过使用 << 1 稍微改进而不是 * 2 ,但是 newMethod还是稍微快点。

关于java - 如何有效地只生成奇数(或偶数)随机数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50613067/

相关文章:

algorithm - 为散点图生成随机数据

javascript - 如何使用javascript随机排序两个同步列表?

java - 如何在@ElementCollection 上指定主键

java - Project Euler #7 Java 代码不工作

java - 字符串缓冲区到字符串转换异常?

python - 一段 Julia 和 Python 代码的优化建议

"and"、 "&&"和 "bitand"之间的 C++ 区别

C++ 隐藏符号增加重定位时间

Jenkins 的 Java API

batch-file - 如何通过批处理文件在随机时间安排任务?