2 回答

TA贡献1812条经验 获得超5个赞
所以这里有两个问题。1) 正如 Carlos Heuberger 所指出的,每次循环时都需要重新初始化变量。2)正如您所指出的,将除法设置为实数除法,而不是整数的“div”运算符需要一些注意。我对您的代码进行了这两项更改(for 循环中的前 5 行;(1.0 * 试验)),它似乎通过了所有测试。你很亲密。
public class RandomWalkers {
public static void main(String[] args) {
int r = Integer.parseInt(args[0]);
int trials = Integer.parseInt(args[1]);
int x = 0;
int xx = 0;
int y = 0;
int yy = 0;
int numSteps = 0;
int totalNumSteps = 0;
double randNum = 0.0;
double avgSteps = 0.0;
for (long i = 0; i < trials; i++) {
x = 0;
xx = 0;
y = 0;
yy = 0;
numSteps = 0;
while (Math.abs(x - xx) + Math.abs(y - yy) != r) {
randNum = Math.random();
if (randNum <= .25) {
// North
yy++;
} else if (randNum <= .5) {
// East
xx++;
} else if (randNum <= .75) {
// South
yy--;
} else {
// West
xx--;
}
numSteps++;
}
totalNumSteps += numSteps;
}
avgSteps = totalNumSteps / (1.0 * trials);
System.out.println("average number of steps = " + avgSteps);
}
}

TA贡献1856条经验 获得超17个赞
当变量声明远离其赋值或使用站点时,往往会发生此类错误。
使用Java Microbenchmark Harness(JMH)我无法看到重新分配和重新声明变量之间的明显性能优势。
Math.Random
但是,当替换为RANDOM.nextInt(4)
和时,我能够看到巨大的(超过 2 倍的速度)switch
import java.util.Random;
public class RandomWalkers {
static final Random RANDOM = new Random();
public static void main(final String[] args) {
int r = Integer.parseInt(args[0]);
int trials = Integer.parseInt(args[1]);
int totalNumSteps = 0;
for (long i = 0; i < trials; i++) {
int x = 0;
int xx = 0;
int y = 0;
int yy = 0;
int numSteps = 0;
while (Math.abs(x - xx) + Math.abs(y - yy) != r) {
switch (RANDOM.nextInt(4)) {
case 0:
// North
yy++;
break;
case 1:
// East
xx++;
break;
case 2:
// South
yy--;
break;
default:
// West
xx--;
}
numSteps++;
}
totalNumSteps += numSteps;
}
double avgSteps = totalNumSteps / (1.0 * trials);
System.out.println("average number of steps = " + avgSteps);
}
}
P0.95 r = 40 的结果
重新分配:299.368 毫秒/操作
重新声明RandomIntSwitch:139.107 毫秒/操作
我们可以做得更好
显式if
条件虽然可读性稍差,但(在这种情况下)比switch
此外,由于我们在单线程上下文中运行,我们可以将 替换java.util.Random
为java.util.concurrent.ThreadLocalRandom
。
此外,显式转换double
比乘以更清晰,1.0
并为我们节省了两个字节码。
P0.95 r = 40 的结果
重新分配:299.368 毫秒/操作
重新声明RandomIntSwitch:139.107 毫秒/操作
重新声明ThreadLocalRandomIntIf:122.539 ms/op
下面的代码快了将近 2.5 倍。
package com.stackoverflow.q56030483;
import java.util.concurrent.ThreadLocalRandom;
@SuppressWarnings("javadoc")
public class RandomWalker {
public static void main(final String[] args) {
int r = Integer.parseInt(args[0]);
int trials = Integer.parseInt(args[1]);
int totalNumSteps = 0;
final ThreadLocalRandom threadLocalRandom = ThreadLocalRandom.current();
for (long i = 0; i < trials; i++) {
int x = 0;
int xx = 0;
int y = 0;
int yy = 0;
int numSteps = 0;
while (Math.abs(x - xx) + Math.abs(y - yy) != r) {
final int direction= threadLocalRandom.nextInt(4);
// North
if (direction == 0) {
yy++;
// East
} else if (direction == 1) {
xx++;
// South
} else if (direction == 2) {
yy--;
// West
} else {
xx--;
}
numSteps++;
}
totalNumSteps += numSteps;
}
System.out.println("average number of steps = " + totalNumSteps / (double) trials);
}
}
Benchmark (arg) Mode Cnt Score Error Units
RandomWalkers.reassign 3 sample 37256 1.611 ± 0.002 ms/op
RandomWalkers.reassign:reassign·p0.00 3 sample 1.475 ms/op
RandomWalkers.reassign:reassign·p0.50 3 sample 1.593 ms/op
RandomWalkers.reassign:reassign·p0.90 3 sample 1.686 ms/op
RandomWalkers.reassign:reassign·p0.95 3 sample 1.780 ms/op
RandomWalkers.reassign:reassign·p0.99 3 sample 1.999 ms/op
RandomWalkers.reassign:reassign·p0.999 3 sample 2.507 ms/op
RandomWalkers.reassign:reassign·p0.9999 3 sample 4.367 ms/op
RandomWalkers.reassign:reassign·p1.00 3 sample 10.371 ms/op
RandomWalkers.reassign 10 sample 3528 17.029 ± 0.063 ms/op
RandomWalkers.reassign:reassign·p0.00 10 sample 15.548 ms/op
RandomWalkers.reassign:reassign·p0.50 10 sample 16.712 ms/op
RandomWalkers.reassign:reassign·p0.90 10 sample 18.416 ms/op
RandomWalkers.reassign:reassign·p0.95 10 sample 18.842 ms/op
RandomWalkers.reassign:reassign·p0.99 10 sample 20.690 ms/op
RandomWalkers.reassign:reassign·p0.999 10 sample 27.636 ms/op
RandomWalkers.reassign:reassign·p0.9999 10 sample 36.176 ms/op
RandomWalkers.reassign:reassign·p1.00 10 sample 36.176 ms/op
RandomWalkers.reassign 40 sample 227 268.714 ± 3.270 ms/op
RandomWalkers.reassign:reassign·p0.00 40 sample 251.134 ms/op
RandomWalkers.reassign:reassign·p0.50 40 sample 262.144 ms/op
RandomWalkers.reassign:reassign·p0.90 40 sample 296.223 ms/op
RandomWalkers.reassign:reassign·p0.95 40 sample 299.368 ms/op
RandomWalkers.reassign:reassign·p0.99 40 sample 303.416 ms/op
RandomWalkers.reassign:reassign·p0.999 40 sample 305.136 ms/op
RandomWalkers.reassign:reassign·p0.9999 40 sample 305.136 ms/op
RandomWalkers.reassign:reassign·p1.00 40 sample 305.136 ms/op
RandomWalkers.redeclareRandomIntSwitch 3 sample 69486 0.863 ± 0.001 ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.00 3 sample 0.763 ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.50 3 sample 0.843 ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.90 3 sample 0.925 ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.95 3 sample 1.028 ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.99 3 sample 1.155 ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.999 3 sample 1.721 ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.9999 3 sample 5.181 ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p1.00 3 sample 9.355 ms/op
RandomWalkers.redeclareRandomIntSwitch 10 sample 7072 8.485 ± 0.040 ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.00 10 sample 7.668 ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.50 10 sample 8.143 ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.90 10 sample 9.650 ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.95 10 sample 10.109 ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.99 10 sample 11.960 ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.999 10 sample 20.399 ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.9999 10 sample 25.919 ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p1.00 10 sample 25.919 ms/op
RandomWalkers.redeclareRandomIntSwitch 40 sample 466 130.302 ± 0.872 ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.00 40 sample 123.732 ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.50 40 sample 128.844 ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.90 40 sample 135.083 ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.95 40 sample 139.107 ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.99 40 sample 155.153 ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.999 40 sample 182.452 ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.9999 40 sample 182.452 ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p1.00 40 sample 182.452 ms/op
RandomWalkers.redeclareThreadLocalRandomIntIf 40 sample 96 107.953 ± 2.148 ms/op
RandomWalkers.redeclareThreadLocalRandomIntIf:redeclareThreadLocalRandomIntIf·p0.00 40 sample 99.746 ms/op
RandomWalkers.redeclareThreadLocalRandomIntIf:redeclareThreadLocalRandomIntIf·p0.50 40 sample 107.676 ms/op
RandomWalkers.redeclareThreadLocalRandomIntIf:redeclareThreadLocalRandomIntIf·p0.90 40 sample 113.797 ms/op
RandomWalkers.redeclareThreadLocalRandomIntIf:redeclareThreadLocalRandomIntIf·p0.95 40 sample 122.539 ms/op
RandomWalkers.redeclareThreadLocalRandomIntIf:redeclareThreadLocalRandomIntIf·p0.99 40 sample 130.810 ms/op
RandomWalkers.redeclareThreadLocalRandomIntIf:redeclareThreadLocalRandomIntIf·p0.999 40 sample 130.810 ms/op
RandomWalkers.redeclareThreadLocalRandomIntIf:redeclareThreadLocalRandomIntIf·p0.9999 40 sample 130.810 ms/op
RandomWalkers.redeclareThreadLocalRandomIntIf:redeclareThreadLocalRandomIntIf·p1.00 40 sample 130.810 ms/op
添加回答
举报