2017-02-14 4 views
0

Ich versuche, Sinus (x) in C mit einer Taylor-Serie und Stirling-Approximation für faktoriales annähern, aber ich bekomme wirklich seltsame Antworten für n < 5 und -0 für jedes n => 5. Ich buchstäblich begann erst gestern lernen, damit ich es schätzen würde, wenn einige erfahrene Programmierer einen Blick darauf werfen konnte und mir sagen, was falsch istApproximieren Sine (x) mit einer Taylor-Serie in C und mit vielen Problemen

Taylor-Reihe von Sine

Stirling Angleichung der factorials

#include <stdio.h> 
#include <math.h> 

int main(){ 

float x,n,s,i,e,p,f,r; 
f=M_PI; 
e=2.7182818; 
s=0; 

printf("What value of sine do you want to apporximate?"); 
    scanf("%f", &x); 
printf("With what level of precision do you want to calculate it?"); 
    scanf("%f", &n); 
for(i=0;i<=n; ++i);{ 
    r=((2*i)+1); 
    p=(sqrt(2*r*f)*(pow((r/e),r))); 
    s=s+(((pow((-1),i))*(pow(x,((2*i)+1))))/p); 
} 
printf("the value of sine at %f is %f",x,s); 
} 
+0

sollten Sie 'double's verwenden anstelle von' float's und 'I' und 'n' sollte 'int's. –

+0

Es gibt auch wenig Notwendigkeit, die Fakultät hier anzunähern. Berechnen Sie jeden Ausdruck stattdessen inkremental, dh indem Sie nacheinander eine Termvariable mit ((-x * x)/(i * (i + 1)) 'jeder Iteration multiplizieren. – doynax

Antwort

0

Diese Linie

for(i = 0; i <= n; ++i);{ 

hat ein zusätzliches Semikolon. Sie führen eine leere Schleife aus.

+3

Und außerdem wird dies durch eine Warnung in Ihrem Compiler abgefangen. Wenn du mit C beginnst, schalte bitte alle Warnungen ein und stell nur Fragen darüber, was sie bedeuten, wenn du sie siehst, oder sie werden sie los, wenn du sie verstehst! – dave

0

basierend auf Ihrem formulat ist dies der richtige Code, aber es falsch Ausgabe erzeugen, so dass Sie wieder Ihre formulat überprüfen müssen:

#include <stdio.h> 
#include <math.h> 

int main(){ 

double x,n,s,i,e,p,f; 
f=M_PI; 
e=2.7182818; 
s=0; 
int sign=0;// Adding this type to toggle the sign 

printf("What value of sine do you want to apporximate?"); 
    scanf("%lf", &x);// conversion specifier must be %lf for floating number 
printf("With what level of precision do you want to calculate it?"); 
    scanf("%lf", &n); 
for(i=1;i<=n; i=i+2){ // Correcting the for loop 
    p=sqrt(2*i*f)*pow((i/e),i); 
    s=s+(pow(-1,sign++)*pow(x,i))/p; 
} 
printf("the value of sine at %f is %f",x,s); 
} 
-1

Als sin() eine periodische Funktion ist, sollte ich nie weiter gehen als eine Periode um es zu berechnen. Dies vereinfacht zu viel Mathematik, da Sie nie große faktorielle Zahlen berechnen müssen. In der Tat müssen Sie den Faktor für jeden Ausdruck in der Reihe sogar nicht berechnen, da die Koeffizienten vom letzten abgeleitet werden können, indem Sie nur den vorhergehenden Koeffizienten durch (n-1) und n teilen. Wenn Ihre Eingabe auf einen Zeitraum beschränkt ist (Sie müssen also keinen festen Zeitraum von M_PI verwenden, können Sie sagen, dass Sie einen maximalen Wert von 3.5 haben und Ihre Antworten auf Werte, die größer sind, reduzieren, indem Sie einfach den Division durch M_PI.

sagte Sobald dies, wir Ihre maximale Fehler binden können, wie für den größten Eingang 3.5 wir 3.5^n/n! als letzter Ausdruck unserer Annäherung haben, mit für einige n begrenzt ist, einige maximal auf weniger als Fehler, der die Anzahl der zu berechnenden Terme festlegt

Anstatt zu versuchen, mit der Anzahl der zu berechnenden Terme genau zu sein, werde ich versuchen, einige Vermutungen zu machen Aus einem Algorithmus abgeleitet und Istwerten (zum Beispiel für den maximalen Eingangswert von 3.2)

Dies sind die Werte der Laufzeit an der Position n zur Eingabe von 3.2 und

n | term at position n for input `3.2` 
======+================= 
    8 | 0.27269634 
    12 | 0.00240693 
    16 | 0.00000578 
    18 | 0.00000019 
    20 | 0.00000001 
    21 | 7.9E-10 

So können zeigen wir Hören Sie auf, nur 20 Begriffe der Serie zu berechnen. Dies gilt für die exp()-Funktion, die alle Begriffe hinzugefügt hat und eine einfache Funktion ist.Für die sin() oder cos() Sie, dass eine bessere Fehlerabschätzung erraten können, wenn man bedenkt, dass beide die gleichen Bedingungen der exp() Funktion haben, (auch die erste hat nur die ungeraden Terme hat der zweite nur die geraden Terme)

(x^n)/(n!) - (x^(n+2))/((n+2)!) = (n!*x^n*(1 - x^2/((n+1)*(n+2))))/n! 

, die für jeden Begriff n > 3.2 Mittel

< x^n/n! 

so können wir das gleiche Kriterium wie für die exponentielle anzuwenden.

Dies sagen, dass wir irgendwann aufhören können ... wenn wir unseren Tisch wir weiterhin an, dass sehen werden, zum Beispiel n > 30 die gesamte kumulierte Laufzeit beträgt weniger als 5.3E-18 so können wir dort nicht mehr (für eine double Nummer , mindestens).

#include <stdio.h> 
#include <math.h> /* for the system sin() function */ 

double MySin(double x) /* x must be in the range [0..3.2] */ 
{ 
    int i; 
    const int n = 30; 
    double t = x, acum = x; /* first term, x/1! */ 
    x *= x; /* square the argument so we get x^2 in variable x */ 
    for (i = 3; i < n; i += 2) { 
      t = -t * x/i/(i-1); /* mutiply by -1, x^2 and divide by i and (i-1) */ 
      acum += t; /* and add it to the accum */ 
    } 
    return acum; 
} 

int main() 
{ 
    double arg; 
    for(;;) { 
      if (scanf("%lg", &arg) != 1) 
        break; 
      printf("MySin(%lg) = %lg; sin(%lg) = %lg\n", 
        arg, MySin(arg), arg, sin(arg)); 
    } 
} 

Wenn Sie die Vorteile von den Symmetrien nehmen, dass die sin-Funktion verfügt, können Sie Ihre Domain zu M_PI/4 reduzieren, die kleiner als eins ist, und Sie können auch bei Laufzeit von Macht 18 erhalten rund 17 significative Ziffern stoppen (für eine double), die Ihre Sünde schneller macht.

Schließlich können wir eine gültige für alle reellen Domain sin2() Funktion erhalten:

double sin2(double x) 
{ 
    bool neg = false; 
    int ip = x/2.0/M_PI; 
    x -= 2.0 * M_PI * ip;     /* reduce to first period [-2PI..2PI] */ 
    if (x < 0.0) x += 2.0*M_PI;    /* reduce to first period [0..2PI] */ 
    if (x > M_PI) { x -= M_PI; neg = true; } /* ... first period negative [ 0..PI ] */ 
    if (x > M_PI/2.0) x = M_PI - x;   /* reflection [0..PI/2] */ 
    return neg ? MySin(-x) : MySin(x); 
} 
Verwandte Themen