2016-08-17 11 views
1

Ich habe dieses Stück Code für Calc:Poisson Calc mit hohen faktorielles

public static double CalcPoisson(double m, double u, boolean va) 
{ 
    double answer = 0; 
    if(!va) 
    { 
     answer = (Math.exp(-u)* Math.pow(u, m))/(factorial(m)); 
    } 
    if(va) 
    { 
     for(int i = 0; i < m; i++) 
     { 
      answer = answer + (Math.exp(-u)* Math.pow(u, i))/(factorial(i)); 
     } 
    } 

    return answer; 

Und das war meine Methode factorial

public static double factorial (double n) 
{ 
    return n == 0 ? 1 : n *factorial(n-1); 
} 

Problem ist: der Maximalwert 170 zu berechnen .. .i brauchen viel mehr (wie faktorielle von 500)

ich eine neue Methode geschrieben haben:

public static BigDecimal factorial2 (double n) 
{ 
    BigDecimal fct = BigDecimal.valueOf(1); 
    for(int i = 1; i<=n; i++) 
    { 
     fct = fct.multiply(BigDecimal.valueOf(i)); 
    } 

    return fct; 

Wie kann ich meine neue faktorielle Methode in meiner "CalcPoisson" Methode verwenden? Problem ist, ich kann nicht mit BigDecimal Doppel teilen ...

Danke für die Hilfe :)

For No One:

ich immer noch diese Codezeile in einer Methode, die CalcPoisson verwendet, im immer noch schlecht mit BigDecimal, ich kann damit nicht umgehen.

The Line:

 BigDecimal nenner = CalcPoisson(m, u, false) + (1-p) * CalcPoisson(m, u, true); 
+0

Was funktionierte nicht mit 'double'? Alles, einschließlich Ihres Endergebnisses, ist doppelte Genauigkeit, wenn Sie mehr als diesen BigDezimal-Wert benötigen, der in der Mitte Ihrer Gleichung steckt, wird das nicht helfen. – markspace

+0

Problem ist die Methode factorial funktioniert nur bis 170! Die Idee ist also, BigDecimal statt Double zu verwenden. –

+0

ist (1-p) ist BigDecimal? – Kaushal28

Antwort

-1

Sie können Ihre Doppel zu BigDecimal konvertieren und dann können Sie zwei BigDecimal s teilen, wie folgend:

BigDecimal answer = BigDecimal.ZERO; 
BigDecimal myOwn = new BigDecimal(Double.toString(Math.exp(-u)* Math.pow(u, i))); 
answer = answer.add(myOwn.divide(factorial2(i))); 

Verwenden BigDecimal Factorial zu finden, wie Sie in factorial2() getan haben .

Schließlich Ihre Methode wird wie folgt aussehen:

public static BigDecimal CalcPoisson(double m, double u, boolean va) 
{ 
BigDecimal answer = BigDecimal.ZERO; 
if(!va) 
{ 
    BigDecimal myOwn1 = new BigDecimal(Double.toString((Math.exp(-u)* Math.pow(u, m)))); 
    answer = myOwn1.divide(fakultaet(m)); 
} 
if(va) 
{ 
    for(int i = 0; i < m; i++) 
    { 
     BigDecimal myOwn = new BigDecimal(Double.toString(Math.exp(-u)* Math.pow(u, i))); 
     answer = answer.add(myOwn.divide(factorial2(i))); 
    } 
} 

return answer; 

Unter der Annahme, dass Sie Rückgabetyp der Methode haben fakultaet() BigDecimal ist. Und wenn Sie Rückgabewert double für das gleiche, als versuchen:

answer = myOwn1.divide(new BigDecimal(fakultaet(m))); 

EDIT

BigDecimal nenner = CalcPoisson(m, u, false).add((BigDecimal.ONE.subtract(new BigDecimal(p))).multiply(CalcPoisson(m, u, true))); 
+0

Man Vielen Dank! –

+0

@ T.Setso Sie sind willkommen :) Sie können die Antwort als richtig markieren, wenn es hilfreich ist :) – Kaushal28

+0

Ein anderes Problem: Eine Zeile einer anderen Methode ist: 'BigDecimal Nenner = calcPoisson (m, u, falsch) + (1- p) * calcPoisson (m, u, wahr); ' Das Problem ist jetzt, * ist nicht definiert für BigDecimal –

1

Sie könnten eine neue BigDecimal aus dem Doppel
erstellen Dann können Sie die multiplie Methode verwenden der BigDecimal

fct = fct.multiplie(new BigDecimal(doubleValue)); 
0

Ihr Ansatz ist zu direkt. Solche Schleifen werden normalerweise in Form von while (nextTerm < epsilon) geschrieben, nicht als For-Schleife. Das heißt natürlich vorausgesetzt, Sie können nachweisen, dass die Bedingungen mit i sinken.

Das andere Problem ist, dass, während der Wert des Ausdrucks pow(u,i)/factorial(i) kann in ein Doppel passen, seine Teile sicherlich nicht. Sie müssen das auf andere Weise berechnen. Natürlich verliert man dabei die Präzision, so dass es noch komplizierter wird.

Ich sollte besser aufhören. Mein Mathe-Professor hat versprochen, dass er jeden von uns jagen und töten wird, der versucht hat, Rechnen zu tun, und er war ein ernsthafter Gentleman.

+0

Danke für Ihren Kommentar, ich weiß, dass mein Algorithmus schlecht codiert ist .. Und ich werde versuchen, es besser zu lernen :) –

2
for(int i = 0; i < m; i++) 
{ 
    answer = answer + (Math.exp(-u)* Math.pow(u, i))/(factorial(i)); 
} 

Beachten Sie, dass dieser Algorithmus alle Faktoren von 0 bis m-1 berechnet. Viel schneller und genauer Faktor, der aus:

long fact = 1; 
    for(int i = 0; i < m; i++) { 
     answer = answer + (Math.exp(-u)* Math.pow(u, i))/fact; 
     fact *= (i+1); 
    } 

dann beachten Sie, dass Math.exp (-u) in der Schleife unveränderlich ist, so extrahieren:

long fact = 1; 
double eu = Math.exp(-u); 
for(int i = 0; i < m; i++) { 
    answer = answer + (eu * Math.pow(u, i))/fact; 
    fact *= (i+1); 
} 

Und Sie können auch loswerden die wiederholten Anrufe Math.pow():

long fact = 1; 
double eu = Math.exp(-u); 
double term = u; 
for(int i = 0; i < m; i++) { 
    answer = answer + (eu * term)/fact; 
    fact *= (i+1); 
    term *= u; 
} 

Schließlich können Sie erhalten auch Begriff und tatsächlich zu einem einzigen Parameter (links als Übung für die Schüler) kombinieren.

+0

Danke für Ihren Kommentar, ich weiß, dass mein Algorithmus codiert ist schlecht .. Und ich werde versuchen, es besser zu machen :) –