2013-11-27 61 views
2

我發現了一個解決方案,通過使用BBS算法來計算Pi的數量。但是我遇到了一個問題。如果使用雙變量,我缺少一個精度。有沒有解決它的建議?如何在Java中使用big double numbers?

這裏是我的代碼:

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

要使用一個隱喻:你正在做的是試圖將一個游泳池的水量倒入玻璃杯中,然後將玻璃杯倒入水池中,並期待它被充滿。不,不會,因爲大部分的水不適合放在玻璃杯中,只能倒在地上。