2013-11-27 3 views
2

Я нашел решение для вычисления числа Pi с использованием алгоритма BBS. Но я столкнулся с проблемой. Я пропускаю точность при использовании двойной переменной. Есть ли предложение исправить это?Как использовать в Java большие двойные номера?

Вот мой код:

public class Pi { 
    public static void main(String[] args) { 
     int n = 5; 

     for (int k = 0; k < n; k++) { 
      int a0 = (int) Math.pow(16, k); 

      double a1 = (double) 4/(8 * k + 1); 
      double a2 = (double) 2/(8 * k + 4); 
      double a3 = (double) 1/(8 * k + 5); 
      double a4 = (double) 1/(8 * k + 6); 

      double a5 = a1 - a2 - a3 - a4; 
      double a6 = (double) 1/a0; 
      double elem = a5 * a6; 

      System.out.println(new BigDecimal(elem)); 
     } 
    } 
} 
+4

Вы отметили свой вопрос «bigdecimal». Ты это пробовал? – EJP

ответ

2

Если вам нужна точность BigDecimal, вам нужно использовать ее для всех расчетов. Недостаточно преобразовать результат с double в BigDecimal в конце, потому что к тому времени точность исчезла.

Вы должны преобразовать все ваши aX переменные BigDecimal, и заменить операторы с вызовами соответствующих методов BigDecimal класса:

BigDecimal pi = BigDecimal.ZERO; 
for (int k = 0; k < n; k++) { 
    BigDecimal a0 = new BigDecimal(16).pow(k); 
    BigDecimal a1 = new BigDecimal(4).divide(new BigDecimal(8*k+1), 20, RoundingMode.HALF_UP); 
    BigDecimal a2 = new BigDecimal(2).divide(new BigDecimal(8*k+4), 20, RoundingMode.HALF_UP); 
    BigDecimal a3 = new BigDecimal(1).divide(new BigDecimal(8*k+5), 20, RoundingMode.HALF_UP); 
    BigDecimal a4 = new BigDecimal(1).divide(new BigDecimal(8*k+6), 20, RoundingMode.HALF_UP); 
    BigDecimal a5 = a1.subtract(a2).subtract(a3).subtract(a4); 
    BigDecimal a6 = BigDecimal.ONE.divide(a0, 20, RoundingMode.HALF_UP); 
    pi.add(a5.multiply(a6)); 
    System.out.println(pi); 
} 

Demo on ideone.

+1

@Alex Я исправил ошибку времени выполнения и добавил код, отсутствующий в вашем алгоритме, чтобы скопировать данные в конечное число pi. Я выбрал случайную точность 20; вы можете изменить его в соответствии с вашими потребностями. – dasblinkenlight

+0

Спасибо. Он работает нормально. – Alex

3

Проблема заключается в том, что вы используете двойники во время самого расчета, таким образом, неизбежно теряет точность. Да, вы используете BigDecimal в конце, но только после того, как уже уничтожили данные, поставив их в парном разряде.

Решение состоит в том, чтобы не использовать удвоения в ЛЮБОЙ точке расчета. Используйте BigDecimal для каждого шага.

Чтобы использовать метафору: то, что вы делаете, пытается влить в воду количество воды в бассейне, а затем вылить стекло в бассейн и надеяться, что оно будет заполнено. Нет, этого не будет, потому что большая часть воды не впилась в стекло и просто вылилась на землю.

Смежные вопросы