I wanted to know how I can generate pi to the nth digit. I have a couple of basic ideas.
- Use
Math.PI
and increase the precision (if that's possible)
- Use Euler's formula to generate pi but even here, I would need to increase the precision (I think)
- There is also Srinivasa Ramanujan's formula for generating PI which is known for it's rapid convergence. This formula seems difficult to implement. I believe, I would have to also increase deicmal precision here.
So in short, either way, I would need to increase the precision of BigDecimal
depending on what the nth digit is. How would I go about increasing the precision of BigDecimal
to nth digit? Also, if there is a better and faster of doing this, can you please point me in the correct direction.
EDIT: I just want to generate PI. I don't want to use for calculations. and this is a question about how I can use BigDecimal to implement my ideas of generating PI.
You need to use MathContext
to increase the precision of the BigDecimal
e.g.
MathContext mc = new MathContext(1000);
BigDecimal TWO = new BigDecimal(2, mc);
It's important that ALL the BigDecimal
s you use in your calculations use that MathContext
.
Heron's method should give you 1000 digits precision with only 10 iterations and a million digits with 20 iterations so it's certainly good enough.
Also, create all the constant BigDecimal
s like e.g. 26390
only once at the start of your program.
You can use this code
import java.math.BigDecimal;
import java.math.RoundingMode;
public final class Pi {
private static final BigDecimal TWO = new BigDecimal("2");
private static final BigDecimal FOUR = new BigDecimal("4");
private static final BigDecimal FIVE = new BigDecimal("5");
private static final BigDecimal TWO_THIRTY_NINE = new BigDecimal("239");
private Pi() {}
public static BigDecimal pi(int numDigits) {
int calcDigits = numDigits + 10;
return FOUR.multiply((FOUR.multiply(arccot(FIVE, calcDigits)))
.subtract(arccot(TWO_THIRTY_NINE, calcDigits)))
.setScale(numDigits, RoundingMode.DOWN);
}
private static BigDecimal arccot(BigDecimal x, int numDigits) {
BigDecimal unity = BigDecimal.ONE.setScale(numDigits,
RoundingMode.DOWN);
BigDecimal sum = unity.divide(x, RoundingMode.DOWN);
BigDecimal xpower = new BigDecimal(sum.toString());
BigDecimal term = null;
boolean add = false;
for (BigDecimal n = new BigDecimal("3"); term == null ||
term.compareTo(BigDecimal.ZERO) != 0; n = n.add(TWO)) {
xpower = xpower.divide(x.pow(2), RoundingMode.DOWN);
term = xpower.divide(n, RoundingMode.DOWN);
sum = add ? sum.add(term) : sum.subtract(term);
add = ! add;
}
return sum;
}
}
resource