50桁までのPIの値を計算したい。
小数点以下50桁のJavaでこれを行う方法は?
50桁が必要なため、デフォルトのデータ型ではこれを行うことはできません:50 / log(2)* log(10)=166ビット。ここで、BigDecimalは代わりに使用できるタイプの1つです。ただし、22/7は円周率の近似値にすぎないことを覚えておく必要があります。50桁で正しくするには、はるかに優れた式が必要です(たとえば、モンテカルロ法、テイラー級数など)。
double変数を使用しているので、代わりに、より精度の高いものを使用する必要があります。BigDecimal
クラスを調べてください。
public class PiReCalc {
public static final int N = 1000; // # of terms
public static void main(String[] args) {
BigDecimal sum = new BigDecimal(0); // final sum
BigDecimal term = new BigDecimal(0); // term without sign
BigDecimal sign = new BigDecimal(1.0); // sign on each term
BigDecimal one = new BigDecimal(1.0);
BigDecimal two = new BigDecimal(2.0);
for (int k = 0; k < N; k++) {
BigDecimal count = new BigDecimal(k);
//term = 1.0/(2.0*k + 1.0);
BigDecimal temp1 = two.multiply(count);
BigDecimal temp2 = temp1.add(one);
term = one.divide(temp2,50,BigDecimal.ROUND_FLOOR);
//sum = sum + sign*term;
BigDecimal temp3 = sign.multiply(term);
sum = sum.add(temp3);
sign = sign.negate();
}
BigDecimal pi = new BigDecimal(0);
BigDecimal four = new BigDecimal(4);
pi = sum.multiply(four);
System.out.println("Calculated pi (approx., " + N + " terms and 50 Decimal Places): " + pi);
System.out.println("Actual pi: " + Math.PI);
}
}
出力は
計算された円周率(約、1000の用語と50の小数点以下の桁数):3.14059265383979292596359650286939597045138933077984
実際の円周率:3.141592653589793
ベイリー、ボールウェイン、プルーフの画期的な論文は次のとおりです。http://oldweb.cecm.sfu.ca/projects/pihex/p123.pdf
その間に、さらに高速な数式(同じ原則に従う)が見つかりました:http://en.wikipedia.org/wiki/Bellard%27s_formula
これは、ベラールの公式bigPi(200,2000)の迅速で汚い実装であり、75ミリ秒で小数点以下500桁以上に適しています。
public static BigDecimal bigPi(int max,int digits) {
BigDecimal num2power6 = new BigDecimal(64);
BigDecimal sum = new BigDecimal(0);
for(int i = 0; i < max; i++ ) {
BigDecimal tmp;
BigDecimal term ;
BigDecimal divisor;
term = new BigDecimal(-32);
divisor = new BigDecimal(4*i+1);
tmp = term.divide(divisor, digits, BigDecimal.ROUND_FLOOR);
term = new BigDecimal(-1);
divisor = new BigDecimal(4*i+3);
tmp = tmp.add(term.divide(divisor, digits, BigDecimal.ROUND_FLOOR));
term = new BigDecimal(256);
divisor = new BigDecimal(10*i+1);
tmp = tmp.add(term.divide(divisor, digits, BigDecimal.ROUND_FLOOR));
term = new BigDecimal(-64);
divisor = new BigDecimal(10*i+3);
tmp = tmp.add(term.divide(divisor, digits, BigDecimal.ROUND_FLOOR));
term = new BigDecimal(-4);
divisor = new BigDecimal(10*i+5);
tmp = tmp.add(term.divide(divisor, digits, BigDecimal.ROUND_FLOOR));
term = new BigDecimal(-4);
divisor = new BigDecimal(10*i+7);
tmp = tmp.add(term.divide(divisor, digits, BigDecimal.ROUND_FLOOR));
term = new BigDecimal(1);
divisor = new BigDecimal(10*i+9);
tmp = tmp.add(term.divide(divisor, digits, BigDecimal.ROUND_FLOOR));
int s = ((1-((i&1)<<1)));
divisor = new BigDecimal(2);
divisor = divisor.pow(10*i).multiply(new BigDecimal(s));
sum = sum.add(tmp.divide(divisor, digits, BigDecimal.ROUND_FLOOR));
}
sum = sum.divide(num2power6,digits, BigDecimal.ROUND_FLOOR);
return sum;
}