-1

我的作业说明:http: //media.orvsd.org/FLVS/backup-ap_computer_science_a_v9_gs_-20120821-1900/course_files/flvs/educator_apcsa_v9_gs/module05/rtfmod05/5.06_AssignmentInstructionsBottleCapPrize.pdf

基本上,我必须进行 1000 次试验。每次试用都是我成功挑选“带奖瓶盖”的时候。因此,每次我获得该奖品时,我还必须查看我在获得该奖品之前经历了多少瓶盖。我最终应该输出的是平均需要经过多少瓶盖才能找到奖盖。

我无法在我的程序中获得平均数量的瓶子,这就是我需要帮助的地方。我的平均结果最终并不正确。至于文件的输入和输出,这是任务的一部分,我已经想通了,所以我不需要帮助。还有一件事,前两行 outputFile.println 代码只是为了测试程序是否正常工作。

import java.io.IOException;
import java.io.PrintWriter;
import java.io.File;
import java.util.Scanner;
import java.util.Random;
public class BottleCapPrize
{
public static void main(String [] args) throws IOException
{
    PrintWriter outputFile = new PrintWriter(new File("MonteCarlo.txt"));
    Random randNum = new Random();
    int bottleCapNumber = 0;
    int wins = 0;
    int capsOpened = 0;

    for(int i = 1; i <= 1000; i++)
    {
        bottleCapNumber = randNum.nextInt(5);
        while(bottleCapNumber != 0)
        {
        bottleCapNumber = randNum.nextInt(5);
        capsOpened++;
        }
        if(bottleCapNumber == 0)
        {
            capsOpened++;
            wins++;
        }
    }
    outputFile.println(capsOpened);
    outputFile.println(wins);
    int averageNumberOfBottles = (int)(((double)wins / (double)capsOpened) * 10);
    outputFile.println("The average amount of bottles that need to be opened are: " + averageNumberOfBottles);    
    outputFile.close();


    Scanner inputFile = new Scanner(new File("MonteCarlo.txt"));
    while(inputFile.hasNextLine())
    {
        String token = inputFile.nextLine();
        System.out.println(token);
    }
        inputFile.close();
}
}
4

2 回答 2

2

虽然这可能不是问题的根源,但在我看来

while (bottleCapNumber != 0) {
    bottleCapNumber = randNum.nextInt(5);
    capsOpened++;
}
if (bottleCapNumber == 0) {
    capsOpened++;
    wins++;
}

可以用更直接、更清晰的方式重写。由于在while语句的末尾,bottleCapNumber 必须相等0(否则,您仍然会在 while 语句中循环),它可以被重写。

while (bottleCapNumber != 0) {
    bottleCapNumber = randNum.nextInt(5);
    capsOpened++;
}
capsOpened++;
wins++;

由于加法的结合特性,很容易重新排列

capsOpened++;
while (bottleCapNumber != 0) {
    bottleCapNumber = randNum.nextInt(5);
    capsOpened++;
}
wins++;

这很明显您正在使用基于 1 的编号例程capsOpened

至于除法来计算平均值,正如其他人所指出的那样,您正在强制整数除法,这意味着您不会产生非整数输出(结果只会是完全可能的除法次数) . 这将极大地改变答案。

你需要的是

 double averageNumberOfBottles = ((double)capsOpened / wins);

请注意double. capsOpened这会强制capsOpened将其作为实数值而不是整数值处理。由于capsOpened现在作为实数处理,除以整数也将产生一个实数。自然地,您需要一个实变量来保存结果,因此您不会截断数字。

我也不清楚你为什么决定分开wins/capsOpened,因为这会给你每个开放上限的平均获胜次数。我以为你想要每次获胜的平均打开盖帽数。引入一个狂野的“然后将其乘以 10”可能是试图找出问题所在的剩余部分,但您当然不想要 10 倍的正确答案。

最后一个副业。虽然java.util.Random是一个“好的”随机数生成器,但它不像其他一些选项那样随机。当然它是内置的,并且可以很快返回数字;但是,如果您真的想要更好(更慢)的随机数来源,请使用java.secure.SecureRandom. 在我的测试中,我通常会回来

with java.util.Random : 
4.696
4.948
4.766
4.901
4.832

with java.secure.SecureRandom : 
4.929
5.058
5.065
4.932
4.782

这不足以确定输出差异的静态显着性,但它肯定表明它java.util.Random比很少超过 5.0 标记的随机性要java.secure.SecureRandomjava.util.Random

于 2012-10-12T19:23:11.627 回答
1

您正在计算每次获胜打开的上限,因此平均公式是错误的应该是

 int averageNumberOfBottles = (capsOpened / wins);
于 2012-10-12T19:21:29.250 回答