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

学生平均步数 = 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:在试验 = 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并相应地编辑您的答案:) 您应该为每个试验重置xxyynumSteps 的值,即在第一个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,没有用的主要内容,如果未能解决你的问题,请参考以下文章

Android:将音频转换为浮点数[]

将字符串转换为浮点数时缺少小数点[重复]

关于整数输出为浮点数的问题

如何从张量转换为浮点数

如何将字符串转换为浮点数?

如何将 Vulgar 分数转换为浮点数?