Java 应用程序拒绝将输出显示为浮点数。尝试过 Casting,乘以 1.0,加 0.0,没有任何效果
Java Application refuses to display output as Floating Point. Have tried Casting, multiplying 1.0, adding 0.0, nothing works
问题:
我在计算整数除法和显示为双精度数(浮点数)时遇到问题。
在较低的数字下,它显示为浮点数,但似乎将值四舍五入为 11.0、9.0、28.0 之类的值。在尝试通过其他 StackO 帖子解决问题后,我似乎无法使其保持一致。我已经通过一些解决方案能够让它显示为浮点解决方案,但是 运行 通过测试命令,结果在显示为浮点或不显示时不一致。
作业要求:
编写一个程序 RandomWalkers.java,接受两个整数命令行参数 'r' 和 'trials'。在每个试验独立实验中,模拟随机游走,直到随机游走者距离起点位于曼哈顿距离 r 处。打印平均步数。
随着 'r' 的增加,我们预计随机游走者会采取越来越多的步数。但是还有多少步呢?使用 RandomWalkers.java 制定关于平均步数如何作为 'r'.
函数增长的假设
通过生成随机样本并汇总结果来估计未知量是 Monte Carlo 模拟的一个示例 — 一种广泛用于统计物理学、计算金融和计算机图形学的强大计算技术。
除了java.lang中的库函数(例如Integer.parseInt()
和Math.sqrt()
),您不能调用库函数。仅使用课程中已介绍的 Java 功能(例如,循环和条件,但 不是数组 )。
我尝试过的:
阅读至少 30 多个不同的 Whosebug 和其他各种网站页面,将整数除法显示为浮点数(双精度)等,并尝试了其中的所有内容。
avgSteps = (double) totalNumSteps / trials;
将 some/all 变量更改为 Double
(totalNumSteps * 1.0) / trials;
(totalNumSteps + 0.0) / trials;
有时我会有所突破,但后来我又测试了一点,但它失败了,部分或所有参数都传递给了应用程序。
代码:
下面的代码是代码的清理基础版本,减去了上面的任何测试。
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++) {
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 / trials;
System.out.println("average number of steps = " + avgSteps);
}
}
预期结果:
这是请求的参数,以及作业项目部分中提供的预期输出。
~/Desktop/loops> java RandomWalkers 5 1000000
平均步数 = 14.98188
~/Desktop/loops> java RandomWalkers 5 1000000
平均步数 = 14.93918
~/Desktop/loops> java RandomWalkers 10 100000
平均步数 = 59.37386
~/Desktop/loops> java RandomWalkers 20 100000
平均步数 = 235.6288
~/Desktop/loops> java RandomWalkers 40 100000
平均步数 = 949.14712
~/Desktop/loops> java RandomWalkers 80 100000
平均步数 = 3775.7152
~/Desktop/loops> java RandomWalkers 160 100000
平均步数 = 15113.61108
评分作业(实际结果)
测试 RandomWalkers 的正确性
运行 总共 7 次测试。
测试 1:检查输出格式
% java RandomWalkers 5 10000
平均步数 = 9.0
% java RandomWalkers 10 1000
平均步数 = 18.0
% java RandomWalkers 20 123456
平均步数 = 150.0
% java RandomWalkers 40 1
平均步数 = 726.0
% java RandomWalkers 1 10000
平均步数 = 1.0
% java RandomWalkers 0 333
平均步数 = 0.0
==> 通过
测试 2:检查平均步数(试验 = 10000)
* java RandomWalkers 1 10000
* java RandomWalkers 2 10000
- 学生平均步数 = 2.000000
- 真实平均步数 = 2.6666666666666665
- 99.99% 置信区间 = [2.617080, 2.716254]
- 正确的解决方案将在 10,000 次
中大约有 1 次因运气不佳而无法通过此测试
java RandomWalkers 3 10000
- 学生平均步数 = 3.000000
- 真实平均步数 = 5.5709
- 99.99% 置信区间 =
[5.443408, 5.698392]
- 一个正确的解决方案将在 10,000 次中大约有 1 次因运气不佳而无法通过此测试
java RandomWalkers 4 10000
- 学生平均步数 = 24.000000
- 真实平均步数 = 9.6808
- 99.99% 置信区间 =
[9.444787, 9.916813]
- 一个正确的解决方案将在 10,000 次中大约有 1 次因运气不佳而无法通过此测试
java RandomWalkers 5 10000
- 学生平均步数 = 7.000000
- 真实平均步数 = 14.9775
- 99.99% 置信区间 =
[14.602377, 15.352623]
- 一个正确的解决方案将在 10,000 次中大约有 1 次因运气不佳而无法通过此测试
java RandomWalkers 10 10000
- 学生平均步数 = 52.000000
- 真实平均步数 = 59.1465
- 99.99% 置信区间 =
[57.612929, 60.680071]
- 一个正确的解决方案将在 10,000 次中大约有 1 次因运气不佳而无法通过此测试
java RandomWalkers 20 10000
- 学生平均步数 = 390.000000
- 真实平均步数 = 235.9058
- 99.99% 置信区间 =
[229.737686, 242.073914]
- 一个正确的解决方案将在 10,000 次中大约有 1 次因运气不佳而无法通过此测试
java RandomWalkers 40 10000
- 学生平均步数=2056.000000
- 真实平均步数 = 943.3142
- 99.99% 置信区间 =
[918.599036, 968.029364]
- 一个正确的解决方案将在 10,000 次中大约有 1 次因运气不佳而无法通过此测试
==> 失败
测试 3:检查平均步数(半径 = 5)
* java RandomWalkers 5 100
- 学生平均步数 = 11.000000
- 真实平均步数 = 14.9775
- 99.99% 置信区间 = [11.226273, 18.728727]
- 正确的解决方案将在 10,000 次
中大约有 1 次因运气不佳而无法通过此测试
java RandomWalkers 5 1000
- 学生平均步数 = 7.000000
- 真实平均步数 = 14.9775
- 99.99% 置信区间 =
[13.791258, 16.163742]
- 一个正确的解决方案将在 10,000 次中大约有 1 次因运气不佳而无法通过此测试
java RandomWalkers 5 10000
- 学生平均步数 = 5.000000
- 真实平均步数 = 14.9775
- 99.99% 置信区间 =
[14.602377, 15.352623]
- 一个正确的解决方案将在 10,000 次中大约有 1 次因运气不佳而无法通过此测试
java RandomWalkers 5 100000
- 学生平均步数 = 9.000000
- 真实平均步数 = 14.9775
- 99.99% 置信区间 =
[14.858876, 15.096124]
- 一个正确的解决方案将在 10,000 次中大约有 1 次因运气不佳而无法通过此测试
java RandomWalkers 5 1000000
- 学生平均步数 = 21.000000
- 真实平均步数 = 14.9775
- 99.99% 置信区间 =
[14.939988, 15.015012]
- 一个正确的解决方案将在 10,000 次中大约有 1 次因运气不佳而无法通过此测试
==> 失败
测试 4:检查平均步数(半径 = 0)
* java RandomWalkers 0 1000
* java RandomWalkers 0 100
* java RandomWalkers 0 1
==> 通过
测试5:检查平均步数不是整数
* java RandomWalkers 10 1000
- 学生平均步数 = 70.0
- 正确的解决方案在 10,000
中失败的次数少于 1 次
java RandomWalkers 7 2500
- 学生平均步数=51.0
- 正确的解决方案在 10,000 次测试中失败的次数少于 1 次
java RandomWalkers 3 10000
- 学生平均步数 = 5.0
- 正确的解决方案在 10,000 次测试中失败的次数少于 1 次
==> 失败
测试 6:检查程序每次产生不同的结果
* java RandomWalkers 10 10000
[ repeated twice ]
* java RandomWalkers 20 1000
[ repeated twice ]
* java RandomWalkers 40 2000
[ repeated twice ]
==> 通过
测试 7:检查 trials = 1 时平均步数的随机性
* java RandomWalkers 2 1
[ repeated 1024 times ]
* java RandomWalkers 3 1
[ repeated 8192 times ]
* java RandomWalkers 4 1
[ repeated 65536 times ]
* java RandomWalkers 5 1
[ repeated 1048576 times ]
==> 通过
RandomWalkers 总数:4/7 测试通过!
所以这里有两个问题。
1)正如 Carlos Heuberger 所指出的,您需要在每次循环中重新初始化变量。
2) 如您所述,将除法设为实数除法需要注意,而不是整数的 "div" 运算符。我对您的代码进行了这两项更改(for 循环中的前 5 行;(1.0 * trials)),它似乎通过了所有测试。
你很接近。
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);
}
}
当变量被声明为远离它们的赋值或 use-site.
时,往往会发生此类错误
使用 Java Microbenchmark Harness(JMH) 我无法看到重新分配和重新声明变量之间明显的性能优势。
然而,当用 RANDOM.nextInt(4)
和 switch
替换 Math.Random
时,我能够看到巨大的(超过 2 倍的加速)
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 ms/op
- 重新声明 RandomIntSwitch:139.107 ms/op
我们可以做得更好
明确的 if
条件虽然可读性稍差,但(在这种情况下)比 switch
快
此外,由于我们在单线程上下文中 运行,我们可以将 java.util.Random
替换为 java.util.concurrent.ThreadLocalRandom
。
此外,显式转换为 double
比乘以 1.0
更清晰,并为我们节省了两个字节码。
P0.95 结果为 r = 40
- 重新分配:299.368 ms/op
- 重新声明 RandomIntSwitch:139.107 ms/op
- 重新声明ThreadLocalRandomIntIf:122.539 ms/op
下面的代码快了将近 2.5 倍。
package com.Whosebug.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
问题:
我在计算整数除法和显示为双精度数(浮点数)时遇到问题。
在较低的数字下,它显示为浮点数,但似乎将值四舍五入为 11.0、9.0、28.0 之类的值。在尝试通过其他 StackO 帖子解决问题后,我似乎无法使其保持一致。我已经通过一些解决方案能够让它显示为浮点解决方案,但是 运行 通过测试命令,结果在显示为浮点或不显示时不一致。
作业要求:
编写一个程序 RandomWalkers.java,接受两个整数命令行参数 'r' 和 'trials'。在每个试验独立实验中,模拟随机游走,直到随机游走者距离起点位于曼哈顿距离 r 处。打印平均步数。
随着 'r' 的增加,我们预计随机游走者会采取越来越多的步数。但是还有多少步呢?使用 RandomWalkers.java 制定关于平均步数如何作为 'r'.
函数增长的假设通过生成随机样本并汇总结果来估计未知量是 Monte Carlo 模拟的一个示例 — 一种广泛用于统计物理学、计算金融和计算机图形学的强大计算技术。
除了java.lang中的库函数(例如Integer.parseInt()
和Math.sqrt()
),您不能调用库函数。仅使用课程中已介绍的 Java 功能(例如,循环和条件,但 不是数组 )。
我尝试过的:
阅读至少 30 多个不同的 Whosebug 和其他各种网站页面,将整数除法显示为浮点数(双精度)等,并尝试了其中的所有内容。
avgSteps = (double) totalNumSteps / trials;
将 some/all 变量更改为 Double
(totalNumSteps * 1.0) / trials;
(totalNumSteps + 0.0) / trials;
有时我会有所突破,但后来我又测试了一点,但它失败了,部分或所有参数都传递给了应用程序。
代码:
下面的代码是代码的清理基础版本,减去了上面的任何测试。
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++) {
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 / trials;
System.out.println("average number of steps = " + avgSteps);
}
}
预期结果:
这是请求的参数,以及作业项目部分中提供的预期输出。
~/Desktop/loops> java RandomWalkers 5 1000000
平均步数 = 14.98188
~/Desktop/loops> java RandomWalkers 5 1000000
平均步数 = 14.93918
~/Desktop/loops> java RandomWalkers 10 100000
平均步数 = 59.37386
~/Desktop/loops> java RandomWalkers 20 100000
平均步数 = 235.6288
~/Desktop/loops> java RandomWalkers 40 100000
平均步数 = 949.14712
~/Desktop/loops> java RandomWalkers 80 100000
平均步数 = 3775.7152
~/Desktop/loops> java RandomWalkers 160 100000
平均步数 = 15113.61108
评分作业(实际结果)
测试 RandomWalkers 的正确性
运行 总共 7 次测试。
测试 1:检查输出格式
% java RandomWalkers 5 10000
平均步数 = 9.0
% java RandomWalkers 10 1000
平均步数 = 18.0
% java RandomWalkers 20 123456
平均步数 = 150.0
% java RandomWalkers 40 1
平均步数 = 726.0
% java RandomWalkers 1 10000
平均步数 = 1.0
% java RandomWalkers 0 333
平均步数 = 0.0
==> 通过
测试 2:检查平均步数(试验 = 10000)
* java RandomWalkers 1 10000
* java RandomWalkers 2 10000
- 学生平均步数 = 2.000000
- 真实平均步数 = 2.6666666666666665
- 99.99% 置信区间 = [2.617080, 2.716254]
- 正确的解决方案将在 10,000 次
java RandomWalkers 3 10000
- 学生平均步数 = 3.000000
- 真实平均步数 = 5.5709
- 99.99% 置信区间 =
[5.443408, 5.698392]
- 一个正确的解决方案将在 10,000 次中大约有 1 次因运气不佳而无法通过此测试
java RandomWalkers 4 10000
- 学生平均步数 = 24.000000
- 真实平均步数 = 9.6808
- 99.99% 置信区间 =
[9.444787, 9.916813]
- 一个正确的解决方案将在 10,000 次中大约有 1 次因运气不佳而无法通过此测试
java RandomWalkers 5 10000
- 学生平均步数 = 7.000000
- 真实平均步数 = 14.9775
- 99.99% 置信区间 =
[14.602377, 15.352623]
- 一个正确的解决方案将在 10,000 次中大约有 1 次因运气不佳而无法通过此测试
java RandomWalkers 10 10000
- 学生平均步数 = 52.000000
- 真实平均步数 = 59.1465
- 99.99% 置信区间 =
[57.612929, 60.680071]
- 一个正确的解决方案将在 10,000 次中大约有 1 次因运气不佳而无法通过此测试
java RandomWalkers 20 10000
- 学生平均步数 = 390.000000
- 真实平均步数 = 235.9058
- 99.99% 置信区间 =
[229.737686, 242.073914]
- 一个正确的解决方案将在 10,000 次中大约有 1 次因运气不佳而无法通过此测试
java RandomWalkers 40 10000
- 学生平均步数=2056.000000
- 真实平均步数 = 943.3142
- 99.99% 置信区间 =
[918.599036, 968.029364]
- 一个正确的解决方案将在 10,000 次中大约有 1 次因运气不佳而无法通过此测试
==> 失败
测试 3:检查平均步数(半径 = 5)
* java RandomWalkers 5 100
- 学生平均步数 = 11.000000
- 真实平均步数 = 14.9775
- 99.99% 置信区间 = [11.226273, 18.728727]
- 正确的解决方案将在 10,000 次
java RandomWalkers 5 1000
- 学生平均步数 = 7.000000
- 真实平均步数 = 14.9775
- 99.99% 置信区间 =
[13.791258, 16.163742]
- 一个正确的解决方案将在 10,000 次中大约有 1 次因运气不佳而无法通过此测试
java RandomWalkers 5 10000
- 学生平均步数 = 5.000000
- 真实平均步数 = 14.9775
- 99.99% 置信区间 =
[14.602377, 15.352623]
- 一个正确的解决方案将在 10,000 次中大约有 1 次因运气不佳而无法通过此测试
java RandomWalkers 5 100000
- 学生平均步数 = 9.000000
- 真实平均步数 = 14.9775
- 99.99% 置信区间 =
[14.858876, 15.096124]
- 一个正确的解决方案将在 10,000 次中大约有 1 次因运气不佳而无法通过此测试
java RandomWalkers 5 1000000
- 学生平均步数 = 21.000000
- 真实平均步数 = 14.9775
- 99.99% 置信区间 =
[14.939988, 15.015012]
- 一个正确的解决方案将在 10,000 次中大约有 1 次因运气不佳而无法通过此测试
==> 失败
测试 4:检查平均步数(半径 = 0)
* java RandomWalkers 0 1000
* java RandomWalkers 0 100
* java RandomWalkers 0 1
==> 通过
测试5:检查平均步数不是整数
* java RandomWalkers 10 1000
- 学生平均步数 = 70.0
- 正确的解决方案在 10,000
java RandomWalkers 7 2500
- 学生平均步数=51.0
- 正确的解决方案在 10,000 次测试中失败的次数少于 1 次
java RandomWalkers 3 10000
- 学生平均步数 = 5.0
- 正确的解决方案在 10,000 次测试中失败的次数少于 1 次
==> 失败
测试 6:检查程序每次产生不同的结果
* java RandomWalkers 10 10000
[ repeated twice ]
* java RandomWalkers 20 1000
[ repeated twice ]
* java RandomWalkers 40 2000
[ repeated twice ]
==> 通过
测试 7:检查 trials = 1 时平均步数的随机性
* java RandomWalkers 2 1
[ repeated 1024 times ]
* java RandomWalkers 3 1
[ repeated 8192 times ]
* java RandomWalkers 4 1
[ repeated 65536 times ]
* java RandomWalkers 5 1
[ repeated 1048576 times ]
==> 通过
RandomWalkers 总数:4/7 测试通过!
所以这里有两个问题。 1)正如 Carlos Heuberger 所指出的,您需要在每次循环中重新初始化变量。 2) 如您所述,将除法设为实数除法需要注意,而不是整数的 "div" 运算符。我对您的代码进行了这两项更改(for 循环中的前 5 行;(1.0 * trials)),它似乎通过了所有测试。 你很接近。
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);
}
}
当变量被声明为远离它们的赋值或 use-site.
时,往往会发生此类错误使用 Java Microbenchmark Harness(JMH) 我无法看到重新分配和重新声明变量之间明显的性能优势。
然而,当用 RANDOM.nextInt(4)
和 switch
Math.Random
时,我能够看到巨大的(超过 2 倍的加速)
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 ms/op
- 重新声明 RandomIntSwitch:139.107 ms/op
我们可以做得更好
明确的 if
条件虽然可读性稍差,但(在这种情况下)比 switch
此外,由于我们在单线程上下文中 运行,我们可以将 java.util.Random
替换为 java.util.concurrent.ThreadLocalRandom
。
此外,显式转换为 double
比乘以 1.0
更清晰,并为我们节省了两个字节码。
P0.95 结果为 r = 40
- 重新分配:299.368 ms/op
- 重新声明 RandomIntSwitch:139.107 ms/op
- 重新声明ThreadLocalRandomIntIf:122.539 ms/op
下面的代码快了将近 2.5 倍。
package com.Whosebug.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