-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回の試行を行う必要があります。各トライアルは、「景品付きボトルキャップ」をピッキングに成功したときです。そのため、その賞品を獲得するたびに、その 1 回の試行でその賞品を獲得するまでにボトル キャップを何回使用したかを確認する必要があります。最終的に出力することになっているのは、賞品のキャップを見つけるために通過しなければならなかったボトルのキャップの平均数です。

プログラムでその平均ボトル数を取得するのに苦労しており、それについて助けが必要です。私の平均は最終的には正しくありません。ファイルの入力と出力に関しては、それは割り当ての一部であり、私はすでにそれを理解しているので、そこに助けは必要ありません. もう 1 つ、最初の 2 行のコード 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また、開いたキャップごとの平均勝利数が得られるため、分割することにした理由も明確ではありません。1 勝あたりのオープン キャップの平均数が必要だと思いました。ワイルドな「そしてそれを 10 倍する」の導入は、何がうまくいかなかったのかを理解しようとする際に取り残されたものかもしれませんが、確かに 10 倍の正解は必要ありません。

最後の副業。java.util.Random「OK」な乱数ジェネレーターですが、他のいくつかのオプションほどランダムではありません。確かにそれは組み込まれており、非常に迅速に数値を返します。しかし、より良い (より遅い) 乱数のソースが本当に必要な場合は、 を使用して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

これは、出力の差の静的な有意性を判断するのに十分な実行ではありませんが、5.0 マークをめったに超えない場合java.util.Randomよりもランダム性が低いことを確かに示唆しています。java.secure.SecureRandomjava.util.Random

于 2012-10-12T19:23:11.627 に答える
1

あなたは勝利ごとに開かれたキャップを計算しているので、平均式は間違っています

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