2013-11-02 34 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. 精度是數字的總數。比例是小數點後的位數。

  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','numerator'和'denominator'進行修改似乎需要解決它。 – user2948708

+0

哦,是的。我錯過了其他變量的相同錯誤。 –