2013-11-02 5 views
2

Я использую алгоритм Чудновский для вычисления PI:Почему это разделение с BigDecimal возвращает 0?

Вот код:

import java.math.BigDecimal; 
import java.math.MathContext; 
import java.util.Scanner; 

public class main { 
    public static void main(String[] args) { 
     Scanner reader = new Scanner(System.in); 
     int summationUpperLimit; 
     int precision; 

     System.out.println("Enter the summation upper limit: "); 
     summationUpperLimit = reader.nextInt(); 

     System.out.println("Enter the precision: "); 
     precision = reader.nextInt(); 

     System.out.println(calculatePI(summationUpperLimit, precision)); 
    } 

    private static int calculateFactorial(int n) { 
     int factorial = 1; 

     for (; n > 1; n--) { 
      factorial = factorial * n; 
     } 

     return factorial; 
    } 

    private static BigDecimal calculatePI(int summationUpperLimit, int precision) { 
     BigDecimal reciprocalOfPI = BigDecimal.ZERO; 
     reciprocalOfPI.setScale(precision - 1, BigDecimal.ROUND_HALF_UP); 

     for (int k = 0; k <= summationUpperLimit; k++) { 
      BigDecimal numerator = BigDecimal.valueOf(12 * Math.pow(-1, k) * calculateFactorial(6 * k) * (13591409 + 545140134 * k)); 
      numerator.setScale(precision - 1, BigDecimal.ROUND_HALF_UP); 
      BigDecimal denominator = BigDecimal.valueOf(calculateFactorial(3 * k) + Math.pow(calculateFactorial(k), 3) * Math.pow(640320, 3 * k + 1.5)); 
      denominator.setScale(precision - 1, BigDecimal.ROUND_HALF_UP); 
      // The issue is the line below: 
      reciprocalOfPI = reciprocalOfPI.add(numerator.divide(denominator, BigDecimal.ROUND_HALF_UP)); 
     } 

     return reciprocalOfPI.pow(-1, MathContext.DECIMAL128); 
    } 
} 

Я установил следующий вход:

summationUpperLimit = 0 
precision = 100 

В режиме отладки, Я проверил выход:

numerator = 163096908 
denominator = 512384048.99600077 
reciprocalOfPI = 0 (this value was taken after the division) 

163096908/512384048.99600077 не равно 0 так почему выражение reciprocalOfPI = reciprocalOfPI.add(numerator.divide(denominator, BigDecimal.ROUND_HALF_UP)); установка reciprocalOfPI на 0?

Мое оправдание для установки scale = precision - 1:

  1. Precision является общее количество цифр. Масштаб - это количество цифр после десятичного знака.

  2. В PI есть только 1 цифра перед десятичной точкой.

  3. precision = scale + 1 и поэтому scale = precision - 1

ответ

4

Это, вероятно, вызвано

reciprocalOfPI.setScale(precision - 1, BigDecimal.ROUND_HALF_UP); 

, который должен быть

reciprocalOfPI = reciprocalOfPI.setScale(precision - 1, BigDecimal.ROUND_HALF_UP); 

BigDecimal неизменна. Все его «мутирующие» методы возвращают новый BigDecimal, оставляя исходный неизменным.

+1

Выполнение этой модификации 'reciprocalOfPI',' числитель' и 'знаменатель', похоже, необходимо решить. – user2948708

+0

О да. Я пропустил ту же ошибку в отношении других переменных. –

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