2011-12-03 13 views
8

Volevo sapere come posso generare pi all'ennesima cifra. Ho un paio di idee di base.generando pi all'ennesima cifra java

  1. Usa Math.PI e aumentare la precisione (se è possibile) formula
  2. Usa di Eulero per generare pi greco, ma anche qui, avrei bisogno di aumentare la precisione (credo) Euler's formula for PI
  3. C'è anche Srinivasa La formula di Ramanujan per la generazione di PI, nota per la sua rapida convergenza. Questa formula sembra difficile da implementare. Credo che anche qui dovrei aumentare la precisione delle telecamere.
    enter image description here

Così, in breve, in entrambi i casi, avrei bisogno di aumentare la precisione di BigDecimal seconda di ciò che la cifra è ennesima. Come farei per aumentare la precisione di BigDecimal all'ennesimo numero? Inoltre, se c'è una soluzione migliore e più veloce, puoi indicarmi la direzione corretta.

MODIFICA: voglio solo generare PI. Non voglio usare per i calcoli. e questa è una domanda su come posso usare BigDecimal per implementare le mie idee sulla generazione di PI.

+0

si fa effettivamente necessario generare Pi o hai bisogno per i calcoli? –

+0

Questa è una domanda sulla matematica dietro il calcolo di pi, o su come usare 'BigDecimal'? –

+0

Sto solo usando BigDecimal per implementare le formule PI e non ho bisogno di PI per calcolare, voglio solo generarlo. –

risposta

6
  • Math.PI è di tipo double. Ciò significa circa 15 cifre decimali di precisione, e cioè tutti i dati che hai; nulla produrrà magicamente ulteriori cifre di PI.
  • BigDecimal ha precisione arbitraria. setScale() consente di creare oggetti BigDecimal con la precisione che si desidera e la maggior parte dei metodi aritmetici aumenterà automaticamente la precisione come richiesto, ma ovviamente più precisione, più lentamente saranno tutti i calcoli.
  • La parte più difficile dell'attuazione della formula di Ramanujan sarà ironicamente la sqrt (2) nel fattore costante, perché non c'è sqrt() incorporato per BigDecimal, quindi dovrai scriverne uno tuo.
+0

Ma per la radice quadrata, il buon vecchio metodo di Heron converge abbastanza velocemente anche con un milione (o un miliardo) di cifre precise. –

+0

per la parte sqrt (2), non posso semplicemente usare il valore predefinito? 1.41421356, o cambierà il calcolo in qualche modo? –

+0

@ user681159: beh, non appena si desidera che il valore di PI sia più preciso di quel "valore predefinito", sono necessarie più cifre di sqrt (2). –

3

è necessario utilizzare MathContext per aumentare la precisione del BigDecimal

esempio

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

E 'importante che tutte le BigDecimal s che usate nei calcoli utilizzare tale MathContext. Il metodo di Heron dovrebbe fornire una precisione di 1000 cifre con solo 10 iterazioni e un milione di cifre con 20 iterazioni, quindi è sicuramente abbastanza buono. Inoltre, creare tutte le costanti BigDecimal s come ad es. 26390 solo una volta all'inizio del programma.

+0

Cosa intendi con il metodo di Heron? –

+0

@ user681159 Il metodo di Heron coincide con il metodo di Newton-Raphson per il caso di radici quadrate, nel caso in cui tu abbia familiarità con quest'ultimo. Altrimenti: sta trovando approssimazioni migliori a 'sqrt (a)' tramite 'x_ (n + 1) = 1/2 * (x_n + a/x_n)'. Converge per tutti 'a> 0' e qualsiasi valore iniziale' x_0> 0'. Se si inizia con un'approssimazione abbastanza buona, in ogni passaggio il numero di cifre corrette raddoppia (circa). –

0

È possibile utilizzare questo codice

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

+0

C'è un problema con questo codice che porta a un ciclo infinito in determinate condizioni ;-( –