2013-11-27 37 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

要使用一个隐喻:你正在做的是试图将一个游泳池的水量倒入玻璃杯中,然后将玻璃杯倒入水池中,并期待它被充满。不,不会,因为大部分的水不适合放在玻璃杯中,只能倒在地上。