Java 应用程序拒绝将输出显示为浮点数。试过铸造,乘1.0,加0.0,没有用
Posted
技术标签:
【中文标题】Java 应用程序拒绝将输出显示为浮点数。试过铸造,乘1.0,加0.0,没有用【英文标题】:Java Application refuses to display output as Floating Point. Have tried Casting, multiplying 1.0, adding 0.0, nothing works 【发布时间】:2019-05-07 21:07:13 【问题描述】:问题:
我在计算整数除法并显示为双精度(浮点)时遇到问题。
在较小的数字上,它显示为浮点数,但似乎将值四舍五入为 11.0、9.0、28.0 之类的值。在尝试通过其他 StackO 帖子解决问题后,我似乎无法使其保持一致。我已经通过一些解决方案能够将其显示为浮点解决方案,但是通过测试命令运行,结果在它们是否显示为浮点时不一致。
家庭作业要求:
编写一个程序 RandomWalkers.java,它接受两个整数命令行参数“r”和“trials”。在每个试验独立实验中,模拟随机游走,直到随机游走者与起点的曼哈顿距离为 r。打印平均步数。
随着 'r' 的增加,我们预计随机游走者会采取越来越多的步骤。但是还有多少步骤?使用 RandomWalkers.java 制定关于平均步数如何作为“r”函数增长的假设。
通过生成随机样本并聚合结果来估计未知量是蒙特卡罗模拟的一个例子——一种强大的计算技术,广泛用于统计物理学、计算金融和计算机图形学。
您不能调用除了 java.lang 中的库函数(例如 Integer.parseInt()
和 Math.sqrt()
)。仅使用课程中已经介绍过的 Java 功能(例如,循环和条件,但不是数组)。
我尝试过的:
阅读至少 30 多个不同的 *** 和其他各种网站页面,将整数除法显示为浮点(双)等,并尝试了其中的所有内容。
avgSteps = (double) totalNumSteps / trials;
将部分/所有变量更改为双精度
(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 次测试。
测试一:检查输出格式
% 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
[5.443408, 5.698392]
一个正确的解决方案将在 10,000 次中大约 1 次因运气不佳而未能通过此测试
java RandomWalkers 4 10000
[9.444787, 9.916813]
一个正确的解决方案将在 10,000 次中大约 1 次因运气不佳而未能通过此测试
java RandomWalkers 5 10000
[14.602377, 15.352623]
一个正确的解决方案将在 10,000 次中大约 1 次因运气不佳而未能通过此测试
java RandomWalkers 10 10000
[57.612929, 60.680071]
一个正确的解决方案将在 10,000 次中大约 1 次因运气不佳而未能通过此测试
java RandomWalkers 20 10000
[229.737686, 242.073914]
一个正确的解决方案将在 10,000 次中大约 1 次因运气不佳而未能通过此测试
java RandomWalkers 40 10000
[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
[13.791258, 16.163742]
一个正确的解决方案将在 10,000 次中大约 1 次因运气不佳而未能通过此测试
java RandomWalkers 5 10000
[14.602377, 15.352623]
一个正确的解决方案将在 10,000 次中大约 1 次因运气不佳而未能通过此测试
java RandomWalkers 5 100000
[14.858876, 15.096124]
一个正确的解决方案将在 10,000 次中大约 1 次因运气不佳而未能通过此测试
java RandomWalkers 5 1000000
[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
java RandomWalkers 3 10000
==> 失败
测试 6:检查程序每次产生不同的结果
* java RandomWalkers 10 10000
[ repeated twice ]
* java RandomWalkers 20 1000
[ repeated twice ]
* java RandomWalkers 40 2000
[ repeated twice ]
==>通过
测试 7:在试验 = 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 次测试通过!
【问题讨论】:
发布的代码由于使用整数除法而无法工作。但也要检查所涉及的数学 - 打印出totalNumSteps
的值
请阅读MCVE guide并相应地编辑您的答案:)
您应该为每个试验重置xx
、yy
和numSteps
的值,即在第一个for
循环内,否则numSteps
将始终与第一次迭代
我在许多算法中都看到了与此类似的错误。对于那些来自 C 的人或那些认为重新分配给变量比重新声明变量更快的人来说,这是很常见的。我已经使用 Java Microbenchmark Harness (JMH) 对下面的算法进行了基准测试,而相同的算法将声明的变量尽可能接近其实际使用位置。两者之间的性能几乎相同,没有明显趋势表明哪个实现更快。
【参考方案1】:
所以这里有两个问题。 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);
【讨论】:
重新初始化 x 和 y 是额外的。一开始我没那么仔细看。我还认为 Carlos Heuberger 抓住了这两个问题值得称赞。 @Carlos Heuberger 如果你想自己发布答案,我会删除我的。 谢谢,这是最好的答案。通过我的反复试验,我得到了大约 99% 的东西,并让它按预期工作,但是由于没有重置坐标和步骤,每次 for 循环运行时都会引入其他无法工作的问题,所以我把自己带进了错误的兔子洞。感谢 Jeremy 和 Carlos 引导我朝着正确的方向前进。【参考方案2】:当变量声明远离其赋值或使用位置时,往往会发生此类错误。
使用 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);
r = 40 的 P0.95 结果
重新分配:299.368 毫秒/操作 重新声明RandomIntSwitch:139.107 毫秒/操作我们可以做得更好
显式if
条件虽然可读性稍差,但(在这种情况下)比switch
快
此外,由于我们在单线程上下文中运行,我们可以将java.util.Random
替换为java.util.concurrent.ThreadLocalRandom
。
另外,显式转换为 double
比乘以 1.0
更清晰,并为我们节省了两个字节码。
r = 40 的 P0.95 结果
重新分配:299.368 毫秒/操作 重新声明RandomIntSwitch:139.107 毫秒/操作 重新声明ThreadLocalRandomIntIf:122.539 ms/op下面的代码快了近 2.5 倍。
package com.***.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
【讨论】:
尽管您的答案在性能水平和基本水平上可能是正确的。任务要求我们使用基本 Java 功能而不使用数组、导入库文件等。我非常感谢您提供的信息,因为随着我们知识的扩展以及我们现在的代码,它肯定会帮助我将来如何编码允许使用。 需要注意的重要一点是java.lang.Math's
random
只是简单地委托给java.util.Random
,这意味着两个实现的实际库依赖足迹是相同的。事实上java.util.Random
不是java.lang.Random
,它本来可以在没有 import 语句的情况下被访问,这只是历史的偶然。以上是关于Java 应用程序拒绝将输出显示为浮点数。试过铸造,乘1.0,加0.0,没有用的主要内容,如果未能解决你的问题,请参考以下文章