Генерация Pi до n -й цифр Java
-
27-10-2019 - |
Вопрос
Я хотел знать, как я могу сгенерировать PI до n -й цифры. У меня есть пара основных идей.
- Использовать
Math.PI
и увеличить точность (если это возможно) - Используйте формулу Эйлера, чтобы генерировать PI, но даже здесь мне нужно было бы повысить точность (я думаю)
- Существует также формула Шринивасы Рамануджана для генерации PI, которая известна своей быстрой конвергенцией. Эта формула кажется трудной для реализации. Я считаю, что мне также придется повысить точность Deicmal здесь.
Короче говоря, в любом случае мне нужно было бы повысить точность BigDecimal
в зависимости от того, что такое n -й цифра. Как я бы увеличил точность BigDecimal
на n -й цифр? Кроме того, если это лучше и быстрее сделать это, не могли бы вы указать мне в правильном направлении.
РЕДАКТИРОВАТЬ: Я просто хочу генерировать PI. Я не хочу использовать для расчетов. И это вопрос о том, как я могу использовать BigDecimal для реализации своих идей генерации PI.
Решение
Math.PI
имеет типdouble
. Анкет Это означает около 15 десятичных цифр точности, и это все данные, которые у вас есть; Магически ничто не сделает дополнительные цифры PI.BigDecimal
имеет произвольную точность.setScale()
позволяет создаватьBigDecimal
Объекты с столь же точностью, сколько вы хотите, и большинство методов арифметических средств автоматически повышают точность по мере необходимости, но, конечно, чем более точно, тем медленнее будет все расчеты.- Самая сложная часть внедрения формулы Рамануджана, по иронии судьбы, будет SQRT (2) в постоянном коэффициенте, поскольку нет встроенного SQRT () для
BigDecimal
, так что вам придется написать свой собственный.
Другие советы
Вам нужно использовать MathContext
Чтобы повысить точность BigDecimal
например
MathContext mc = new MathContext(1000);
BigDecimal TWO = new BigDecimal(2, mc);
Важно, чтобы все BigDecimal
вы используете в своих расчетах, используйте это MathContext
Анкет Метод Херона должен предоставить вам точность 1000 цифр только с 10 итерациями и миллионами цифр с 20 итерациями, так что это, безусловно, достаточно хорошо. Также создайте все постоянные BigDecimal
как например 26390
Только один раз в начале вашей программы.
Вы можете использовать этот код
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;
}
}