Использование BigDecimal в Java для вычисления номера PI до 200 десятичных цифр

Чтобы оценить число PI, я хочу, в частности, использовать метод Монте-Карло, применяя его к игре в дартс с кругом радиусом 1 внутри квадрата 1x1. Более подробное описание можно найти здесь. Я хочу, чтобы код Java оценивал PI до 200 цифр. Я использовал BigDecimal, но он показывает 49 десятичных цифр и ставит нулевое число для остальных. Я ценю любую помощь.

import java.util.*;
import java.math.BigDecimal;

public class PiFinder {

    // description
    public static void main(String[] args) {
        Scanner iteration = new Scanner(System.in);
        System.out.print("Enter the number of iteration: ");
        int NoThrows = iteration.nextInt();
        BigDecimal PI = new BigDecimal(PIcalculation(NoThrows));
        PI = PI.setScale(200);

        // Difference of our estimated PI and the actual PI
        BigDecimal Difference = new BigDecimal(0);
        BigDecimal actualPI = new BigDecimal(Math.PI);
        System.out.println("Actual PI: " + actualPI);
        Difference = PI.subtract(actualPI);

        // Display results
        System.out.println("The Number of Throws = " + NoThrows);
        System.out.println("***************************");
        System.out.println("Estimated PI = " + PI);
        System.out.println("Difference = " + Difference);
    }

    // Deteremine a thrown dart is inside the circle
    public static boolean insideCircle(double pos_X, double pos_Y) {
        double distance = Math.sqrt((pos_X * pos_X) + (pos_Y * pos_Y));

        return (distance < 1.0);
    }


    public static double PIcalculation(int NoThrows) {
        Random randomGen = new Random(System.currentTimeMillis());
        int hits = 0;
        double PI = 0;

        for (int i = 1; i <= NoThrows; i++) {

            double pos_X = (randomGen.nextDouble()) * 2 - 1.0;
            double pos_Y = (randomGen.nextDouble()) * 2 - 1.0;

            if (insideCircle(pos_X, pos_Y)) {
                hits++;
            }
        }

        double dthrows = NoThrows;

        // the formule
        PI = (4.0 * (hits / dthrows));

        return PI;
    }
}

person WhiteHat    schedule 23.12.2014    source источник
comment
В то время как double имеет точность 16 знаков после запятой, Math.sqrt может вдвое уменьшить точность до 8. Однако вам нужно использовать BigDecimal повсюду, вам также потребуется много терпения, поскольку каждая цифра занимает в десять раз больше времени. то есть, скажем, 20 цифр занимают секунду, тогда 30 цифр потребуют 300 лет, а 40 цифр потребуют больше, чем возраст Вселенной.   -  person Peter Lawrey    schedule 23.12.2014
comment
Спасибо за ваше объяснение.   -  person WhiteHat    schedule 23.12.2014


Ответы (1)


Ваш PiCalculation возвращает двойное значение, вы не можете ожидать большей точности с этим.

Используйте BigDecimal везде, если хотите пойти дальше.

Но в любом случае с этим методом, даже при 10 ^ 10 бросках, у вас будет только 10 знаков после запятой.

49 десятичных знаков, которые у вас были с вашим двойником, были из-за двойного отсутствия точности

person yunandtidus    schedule 23.12.2014
comment
плюс 1, double создаст до 52 цифр при преобразовании в BigDecimal, но сам имеет в лучшем случае только 16 цифр точности. - person Peter Lawrey; 23.12.2014
comment
@yunandtidus: Большое спасибо. Я изменю их все на BigDecimal и в любом случае опубликую вывод здесь. - person WhiteHat; 23.12.2014
comment
Обратите внимание, что для того, чтобы иметь 200 десятичных знаков, вам нужно выполнить 10 ^ 200 бросков, это невычислимо! - person yunandtidus; 23.12.2014
comment
Так что бы вы предложили? Есть ли какой-нибудь доступный способ? - person WhiteHat; 23.12.2014