Генерирование пи к n-й цифре Java

Я хотел знать, как я могу сгенерировать пи к n-й цифре. У меня есть пара основных идей.

  1. использование Math.PI и повысить точность (если это возможно)
  2. Используйте формулу Эйлера для генерации числа Пи, но даже здесь мне нужно было бы повысить точность (я думаю)Формула Эйлера для PI
  3. Существует также формула Шриниваса Рамануджана для генерации ПИ, которая известна своей быстрой конвергенцией. Эта формула кажется сложной для реализации. Полагаю, мне бы здесь также пришлось повысить точность бейка.

Короче говоря, в любом случае, мне нужно увеличить точность BigDecimal в зависимости от того, что n-ая цифра. Как бы я пошел на повышение точности BigDecimal к цифре n? Кроме того, если это будет лучше и быстрее, не могли бы вы указать мне правильное направление.

РЕДАКТИРОВАТЬ: я просто хочу генерировать PI. Я не хочу использовать для расчетов. и это вопрос о том, как я могу использовать BigDecimal для реализации моих идей генерации PI.

3 ответа

Решение
  • 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);

Важно, чтобы ВСЕ BigDecimals вы используете в своих расчетах использовать это 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;
}
}

ресурс

Другие вопросы по тегам