Pregunta

Quería saber cómo puedo generar PI para el enésimo dígito. Tengo un par de ideas básicas.

  1. Usar Math.PI y aumentar la precisión (si es posible)
  2. Use la fórmula de Euler para generar PI, pero incluso aquí, necesitaría aumentar la precisión (creo)Euler's formula for PI
  3. También está la fórmula de Srinivasa Ramanujan para generar PI que es conocida por su rápida convergencia. Esta fórmula parece difícil de implementar. Creo que también tendría que aumentar la precisión deicmal aquí.
    enter image description here

Entonces, en resumen, de cualquier manera, necesitaría aumentar la precisión de BigDecimal dependiendo de cuál sea el enésimo dígito. ¿Cómo haría para aumentar la precisión de BigDecimal a enésimo dígito? Además, si hay un mejor y más rápido de hacer esto, ¿puedes señalarme en la dirección correcta?

Editar: solo quiero generar Pi. No quiero usar para los cálculos. Y esta es una pregunta sobre cómo puedo usar BigDecimal para implementar mis ideas para generar PI.

¿Fue útil?

Solución

  • Math.PI es de tipo double. Eso significa alrededor de 15 dígitos decimales de precisión, y esos son todos los datos que tiene; Nada hará que aparezcan mágicamente dígitos adicionales de Pi.
  • BigDecimal tiene precisión arbitraria. setScale() te permite crear BigDecimal Los objetos con tanta precisión como desee y la mayoría de los métodos aritméticos aumentarán automáticamente la precisión según sea necesario, pero, por supuesto, cuanto más precisión, más lentos serán todos los cálculos.
  • La parte más difícil de implementar la fórmula de Ramanujan será irónicamente el sqrt (2) en el factor constante, porque no hay sqrt () incorporado para BigDecimal, entonces tendrás que escribir el tuyo.

Otros consejos

Necesitas usar MathContext para aumentar la precisión del BigDecimal

p.ej

MathContext mc = new MathContext(1000);
BigDecimal TWO = new BigDecimal(2, mc);

Es importante que todos los BigDecimalS Usas en tus cálculos usa eso MathContext. El método de Heron debería darle una precisión de 1000 dígitos con solo 10 iteraciones y un millón de dígitos con 20 iteraciones, por lo que ciertamente es lo suficientemente bueno. Además, crea toda la constante BigDecimals como eg 26390 Solo una vez al comienzo de su programa.

Puedes usar este código

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;
}
}

recurso

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top