Моделирование Монте-Карло Пи в простой Java?

Я пытаюсь сделать знаменитое моделирование Монте-Карло, чтобы оценить число пи для моего курса Java. Вот симуляция:

 public class Darts
    {
    //"throwing" a dart
    public static boolean [] dartThrow(int r, int d){
        boolean [] booleanArray = new boolean[d];
        for(int i = 0; i < d; i++){
        double xCoord = Math.random() * 2;
        double yCoord = Math.random() * 2;
        if((Math.pow(xCoord,2) + Math.pow(yCoord,2)) <= r){
            booleanArray[i] = true;
        }
        else{
            booleanArray [i] = false;
        }
       }
       return booleanArray;
    }

    //calculating pi from throwing results
    public static double piEstimater(boolean [] h, int d){
        int trueCounter = 0;
        for(int i = 0; i < h.length; i++){
            if(h[i] == true){
                trueCounter++;
            }
        }
        return 4 * ((double)trueCounter / d);
    }

    //printing results
    public static void printer(double [] a){
        System.out.println("     Pi Estimation Tool    ");
        System.out.println("---------------------------");
        for(int i = 0; i < a.length; i++){
            System.out.print("Trial [" + i + "]: pi = ");
            System.out.printf("%6f\n", a[i]);
        }
    }

    public static void main(String[] args){
        //variables
        Scanner in = new Scanner(System.in);
        int radius = 1;
        int darts;
        int trials;

        System.out.println("Enter the number of darts to calculate for: ");
        darts = in.nextInt();
        System.out.println("Enter the number of trials to calculate for: ");
        trials = in.nextInt();

        double [] arrayOfEstimates = new double [trials];
        int i = 0;
        for(double a : arrayOfEstimates){
           boolean [] hitCounter = dartThrow(radius, darts);
           double piEstimate = piEstimater(hitCounter, darts);
           arrayOfEstimates[i] = piEstimate;
           i++;
        }

        printer(arrayOfEstimates);
    }
}

Я создал код, который выполняется правильно, за исключением того, что результаты никогда не превышают ~ 0,8. Я хотел бы просто предположить, что это происходит из-за того, что случайных чисел очень мало, но если это происходит каждый раз, когда что-то ДОЛЖНО быть неправильным, верно? Пожалуйста, имейте в виду, что этот код содержит почти все методы Java, которые я знаю, поэтому я был бы признателен, если бы вы воздержались от включения чего-либо более «продвинутого». Спасибо!


person Ely Eastman    schedule 17.08.2014    source источник
comment
Пожалуйста, сократите свой код, удалив вместо этого биты, которые вы можете жестко закодировать, и удалив целые функции, которые используются только для ведения журнала консоли и т. Д. Это упражнение, которое мы все делаем, обычно помогает нам найти проблему, прежде чем задавать вопрос. Затем, когда у вас есть минимальный пример, запустите код и вслух объясните, что он должен делать вымышленному другу (или настоящему другу, если ему не все равно). Это почти гарантировано, чтобы вы нашли, что не так, потому что вы будете объяснять что-то и смотреть на код, и вдруг подождите, это не то, что код делает, о, конечно   -  person Mike 'Pomax' Kamermans    schedule 17.08.2014


Ответы (1)


Идея расчета PI с использованием метода Монте-Карло состоит в том, чтобы выбрать случайные точки в квадрате и подсчитать их долю, попадающую в область круга, ограниченного этим квадратом. Если равномерно выбрано достаточное количество точек, дробь будет близка к площади круга, деленной на площадь ограничивающего квадрата:

fraction = PI*r^2/(2r)^2

и поэтому

PI = fraction * 4.

Теперь, поскольку вы выбираете только положительные координаты, если предположить, что центр круга находится в начале координат (0,0), мы выбираем только точки в верхней правой четверти круга и его ограничивающего квадрата, но уравнение остается прежним.

Если ваш круг имеет радиус r, вы должны выбрать координаты от 0 до r.

Поэтому вы должны изменить это:

    double xCoord = Math.random() * 2;
    double yCoord = Math.random() * 2;

К этому :

    double xCoord = Math.random() * r;
    double yCoord = Math.random() * r;

Кроме того, условие должно быть ((Math.pow(xCoord,2) + Math.pow(yCoord,2)) <= r*r).

Конечно, вы можете упростить его, исключив r и предположив, что радиус равен 1.

В этом случае условие будет ((Math.pow(xCoord,2) + Math.pow(yCoord,2)) <= 1), а выборка координат будет между 0 и 1.

person Eran    schedule 17.08.2014
comment
Поскольку радиус равен 1, ширина квадрата будет равна 2, а поскольку Math.random генерирует число от 0,0 до 1,0, не даст ли умножение на два полный диапазон координат от 0 до 2,0? Несмотря на это, умножение на радиус приблизило меня к числу пи. - person Ely Eastman; 17.08.2014
comment
@ElyBeauEastman Если круг находится в центре (0,0), поскольку вы получаете только случайные положительные числа, вы можете набирать очки только в пределах четверти круга. эта четверть связана квадратом (0,0) с (1,1). - person Eran; 17.08.2014