Монте-Карло расчет пи с использованием случайно сгенерированных данных в Java

Я работаю над программой, которая рассчитывает pi на основе случайно сгенерированных чисел с плавающей точкой, представляющих координаты x,y на графике. Каждая координата x,y возводится в степень 2 и сохраняется в двух отдельных массивах. Координаты распределены равномерно на графике с интервалом 0,1.

Программа добавляет координаты x,y, и если они меньше 1, то точки расположены внутри круга диаметром 1, как показано на диаграмме ниже.

Затем я использовал формулу,

π ≈ 4 Вт / н

работать пи Где w - количество точек в круге, а n - количество координат x или y в массивах.

Когда я устанавливаю n до 10000 000 (размер массива), он генерирует наиболее точный расчет числа 15-16 знаков после запятой. Однако после выделения 4 ГБ ОЗУ для конфигурации запуска и установки значения n в 100 000 000 пи получается 0,6710...

Мне было интересно, почему это может происходить? Извините, если это глупый вопрос.. код ниже.

import java.text.DecimalFormat;
import java.util.Random;

public class random_pi {

    public random_pi() {

        float x2_store[] = new float[10000000];
        float y2_store[] = new float[10000000];
        float w = 0;

        Random rand = new Random();
        DecimalFormat df2 = new DecimalFormat("#,###,###");

        for (int i = 0; i < x2_store.length; i++) {
            float x2 = (float) Math.pow(rand.nextFloat(), 2);
            x2_store[i] = x2;
            float y2 = (float) Math.pow(rand.nextFloat(), 2);
            y2_store[i] = y2;
        }

        for (int i = 0; i < x2_store.length; i++) {
            if (x2_store[i] + y2_store[i] < 1) {
                w++;
            }
        }

        System.out.println("w: "+w);
        float numerator = (4*w);
        System.out.printf("4*w: " + (numerator));
        System.out.println("\nn: " + df2.format(x2_store.length));
        float pi = numerator / x2_store.length;

        String fmt = String.format("%.20f", pi);
        System.out.println(fmt);

        String pi_string = Double.toString(Math.abs(pi));
        int intP = pi_string.indexOf('.');
        int decP = pi_string.length() - intP - 1;
        System.out.println("decimal places: " + decP);
    }

    public static void main(String[] args) {
        new random_pi();
    }
}

1 ответ

Решение

Проблема здесь:

float w = 0;
float numerator = (4*w);

float недостаточно точности, измените ее на int или же double:

Как этот рабочий пример кода:

import java.text.DecimalFormat;
import java.util.Random;

public class random_pi {

    public random_pi() {

        float x2_store[] = new float[100000000];
        float y2_store[] = new float[100000000];
        int w = 0;

        Random rand = new Random();
        DecimalFormat df2 = new DecimalFormat("#,###,###");

        for (int i = 0; i < x2_store.length; i++) {
            float x2 = (float) Math.pow(rand.nextFloat(), 2);
            x2_store[i] = x2;
            float y2 = (float) Math.pow(rand.nextFloat(), 2);
            y2_store[i] = y2;
        }

        for (int i = 0; i < x2_store.length; i++) {
            if (x2_store[i] + y2_store[i] < 1) {
                w++;
            }
        }

        System.out.println("w: "+w);
        int numerator = (4*w);
        System.out.printf("4*w: " + (numerator));
        System.out.println("\nn: " + df2.format(x2_store.length));
        float pi = ((float)numerator) / x2_store.length;

        String fmt = String.format("%.20f", pi);
        System.out.println(fmt);

        String pi_string = Double.toString(Math.abs(pi));
        int intP = pi_string.indexOf('.');
        int decP = pi_string.length() - intP - 1;
        System.out.println("decimal places: " + decP);
    }

    public static void main(String[] args) {
        new random_pi();
    }
}

выход:

w: 78544041
4*w: 314176164
n: 100,000,000
3.14176154136657700000
decimal places: 15

И вам не нужно хранить результаты, как этот рабочий пример кода:

import java.text.DecimalFormat;
import java.util.Random;

public class pi {

    public pi() {
        double n=100000000; 
        double w = 0;

        Random rand = new Random();
        DecimalFormat df2 = new DecimalFormat("#,###,###");

        for (int i = 0; i < n; i++) {
            double x = rand.nextFloat(); 
            double y = rand.nextFloat();  
            if ((x*x + y*y) < 1.0) w++;
        }

        System.out.println("w: "+w);//w: 7852372.0
        double numerator = (4*w);
        System.out.printf("4*w: " + (numerator));//4*w: 3.1409488E7
        System.out.println("\nn: " + df2.format(n));//n: 10,000,000
        double pi = numerator / n;

        final String fmt = String.format("%.20f", pi);
        System.out.println(fmt);//3.14094877243042000000

        String pi_string = Double.toString(Math.abs(pi));
        int intP = pi_string.indexOf('.');
        int decP = pi_string.length() - intP - 1;
        System.out.println("decimal places: " + decP);//decimal places: 14
    }

    public static void main(String[] args) {
        new random_pi();
    }
}

выход:

w: 78539606
4*w: 314158424
n: 100,000,000
3.14158439636230470000
decimal places: 16
Другие вопросы по тегам