通过查看有关仅偶数或奇数生成的其他问题,我很好奇哪种方法最有效(就速度而言)。
例如,假设我想生成许多从 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/