2016-09-07 1 views
0

Ich benutze mclaurins Reihe, um Arccos zu berechnen (x^2-1), aber wenn ich es mit einem Ergebnis von math.acos vergleiche, unterscheidet es sich. Hier ist mein Code:Was ist los in Maclaurin-Serie Arccos-Berechnungen mit Java?

public class Maclaurin { 

    public static int factorial(int fact) { 
     if(fact==0) 
      return 1; 
     return fact*factorial(fact-1); 
    } 

    public static void main(String[] args) { 
    int i, j; 
    double function = 0, x,result; 

    x=0; 

     for (int n = 0; n < 8; n++) { 

      function=((factorial(2*n))/(Math.pow(4, n)*Math.pow(factorial(n),2)*(2*n+1)))*Math.pow((Math.pow(x, 2)-1),2*n+1); 
      result=(Math.PI/2)-function; 

      System.out.println("x= "+x+" y= "+result); 
      System.out.println("Test "+Math.acos(Math.pow(x, 2)-1)); 
      x+=0.13; 
     } 




    } 


    } 

Programm output. test is a value calculated with Math.arccos and it differs from y calculated with mclaurins formula: 

    x= 0.0 y= 2.5707963267948966 
    Test 3.141592653589793 
    x= 0.13 y= 1.7291549939933966 
    Test 2.9574849820283498 
    x= 0.26 y= 1.6236496851024964 
    Test 2.771793621843802 
    x= 0.39 y= 1.5848621264898726 
    Test 2.5828078861333155 
    x= 0.52 y= 1.5725761587226181 
    Test 2.3885331918392687 
    x= 0.65 y= 1.5708496332463704 
    Test 2.1864594293995867 
    x= 0.78 y= 1.570796415168701 
    Test 1.9731661516473589 
    x= 0.91 y= 1.5707963267948972 
    Test 1.7435543826662978 

EDIT: Neuer Code, in dem Berechnungen in Maclaurinschen Funktion sind, und ich nenne es von der Hauptfunktion. funktioniert gut für alle Werte außer dem ersten 3: Paket Maclaurin;

public class Maclaurin { 
    private static double x; 

//public static int factorial(int fact) { 
// if(fact==0) 
//  return 1; 
// return fact*factorial(fact-1); 
//} 
    public static double factorial(int fact) { 
    if(fact==0) 
     return 1; 
    return fact*factorial(fact-1); 
} 

public static void main(String[] args) 
    { 
     x = 0; 
     for (int i=0;i<8;i++) 
      { 
       maclaurin(x); 
       x=x+0.14; 
      } 

    } 

public static void maclaurin(double value){ 
    double function = 0, x, result; 

    x =value; 

    for (int n = 0; n < 20; n++) { 
     function += ((factorial(2 * n))/(Math.pow(4, n) * Math.pow(factorial(n), 2) * (2 * n + 1))) 
       * Math.pow((Math.pow(x, 2) - 1), 2 * n + 1); 
    } 

    result = (Math.PI/2) - function; 
    System.out.println("x= " + x + " y= " + result); 
    System.out.println("Test " + Math.acos(Math.pow(x, 2) - 1)); 
} 




} 
+0

Ist es unterscheiden? Ich kann keinen Unterschied sehen. Vielleicht könnten wir, wenn wir den Unterschied sehen könnten, über den Sie sprechen, besser helfen? – Andreas

+0

@Andreas hier ist die Programm-Ausgabe hinzugefügt –

+0

@Andreas ich überprüfte Formel mehrmals und fand keine Fehler –

Antwort

2

Die Fakultät von 16, die in der Schleife erscheint, ist größer als MAX_INT.

ich:

>> factorial(16) 
2.0923e+013 
>> 2^31 
2.1475e+009 

in Octave. Sie müssen eine analytische Vereinfachung vornehmen, um diese im Bereich zu halten oder double anstelle von int dort zu verwenden.

+0

obwohl es ein Problem ist, beantwortet es die Frage nicht.Er hat auch falsche Werte für kleine Eingaben. – JohnnyAW

+0

@Brick Ich werde das überprüfen, aber da JohnnyAW bereits gesagt hat, dass es nicht einmal für kleine Werte funktioniert –

+1

Ich habe nicht überprüft, wie weit diese Serie gut ist, da Sie den offensichtlichen Codierungsfehler haben Größe der Ganzzahl. Ich stimme @JohnnyAW jedoch zu, dass Sie nicht erwarten können, dass die Serie zur richtigen Antwort konvergiert, es sei denn, Sie sind "nahe genug" an dem Punkt, an dem Sie die Erweiterung durchgeführt haben. Wie weit Sie gehen können, hängt von der Art der Funktion, der Anzahl der von Ihnen gepflegten Begriffe und der Genauigkeit ab. Wenn Sie diesen Teil nicht verstehen, empfehle ich, über Maclauren-Serien woanders zu lesen oder einige Fragen an die Mathe-SE zu stellen. Wenn Sie sehr große Faktoren benötigen, sollten Sie auch die Stirling-Approximation in Erwägung ziehen. – Brick

2

Ich denke du verstehst nicht, was Maclaurin-Serie (taylor's Serie) eigentlich macht. Es kann einen ungefähren Wert berechnen. Sie erhalten den genauen Wert nur für n -> ∞. Da wir das nicht berechnen können, müssen wir einige n definieren und unsere Berechnung dort stoppen. Sie müssen jeden einzelnen Teil des Summs hinzufügen, um den tatsächlichen Wert zu erhalten. Also im Grunde sollten Sie iterieren n und fügen Sie den berechneten Wert zu function und nach der Schleife können Sie result berechnen:

public static void main(String[] args){ 
    double x = 0; 

    for(int i = 0;i < 8;i++){ 
     System.out.println("x: " + x + " maclaurin: " + maclaurin(x)); 
     System.out.println("Test: " + Math.acos(Math.pow(x, 2) - 1)); 

     x += 0.14; 
    } 
} 

public static double maclaurin(double x){ 
    double function = 0; 

    for (int n = 0; n < 10; n++) { 
     function += ((factorial(2 * n))/(Math.pow(4, n) * Math.pow(factorial(n), 2) * (2 * n + 1))) 
       * Math.pow((Math.pow(x, 2) - 1), 2 * n + 1); 
    } 

    return (Math.PI/2) - function; 
} 

auf diese Weise ich ziemlich nah dran Werte bekam:

x: 0.0 maclaurin: 2.962490972738185 
Test: 3.141592653589793 
x: 0.14 maclaurin: 2.8972172328920296 
Test: 2.9432779368601296 
x: 0.28 maclaurin: 2.7366715068800485 
Test: 2.7429790581451043 
x: 0.42000000000000004 maclaurin: 2.5381695201901326 
Test: 2.5385256934250617 
x: 0.56 maclaurin: 2.3273181153351756 
Test: 2.327323409412957 
x: 0.7000000000000001 maclaurin: 2.105981109221438 
Test: 2.1059811170704963 
x: 0.8400000000000001 maclaurin: 1.8696239609917407 
Test: 1.8696239609918046 
x: 0.9800000000000001 maclaurin: 1.6104066839613247 
Test: 1.6104066839613247 

es scheint, dieses Ergebnis ist nicht so gut für x in der Nähe von 0. Sie können n erhöhen, um bessere Ergebnisse zu erhalten, aber irgendwann erhalten Sie NaN, da factorial irgendwann überläuft.

vergessen Sie nicht factorial wie @Brick zu ändern vorgeschlagen:

public static double factorial(int fact) { 
    if(fact==0) 
     return 1; 
    return fact*factorial(fact-1); 
} 

, wenn Sie sich fragen, wie factorial in einer iterativen Art und Weise zu berechnen, hier ist ein Beispiel (es spielt eigentlich keine Rolle in diesem speziellen Fall , aber hey, wir sind hier, um neue Dinge zu lernen, rechts):

public static double factorial(int fact) { 
    double result = 1; 
    while(fact > 1){ 
     result *= fact--; 
    } 
    return result; 
} 

EDIT: geändert fact Parameter int

EDIT2: maclaurin Funktion eingewickelt und hinzugefügt mehr Werte

EDIT3: hinzugefügt iterative factorial

+0

Sie sollten wahrscheinlich den Parameter in 'faktorial()' zurück zu einem 'int' ändern, aber den Rückgabewert als' double' beibehalten. – Andreas

+0

@Andreas yeah, 'fact == 0' wäre sonst etwas" dreckig ":) – JohnnyAW

+0

Ich weiß, du bleibst bei der Frage, aber' factorial() 'sollte eine Schleife sein, keine Rekursion. Sie werden es wahrscheinlich nicht mit Werten benennen, die hoch genug sind, um ein Problem zu sein, aber Rekursion kann 'StackOverflowError' verursachen. Außerdem ist das Schleifen schneller als die Rekursion. – Andreas