2016-10-04 3 views
1

Ich machte ein Programm, das die jeweilige Taylor-Serie berechnet, aber der Professor will, dass wir es ändern, indem wir zuerst teilen und dann multiplizieren. Dies ist mein Code und ich verwende die divide() für den ersten Teil. Meine power() und fact() sind nur Verweise auf meinen alten Code.Taylor-Serie in C mit Funktionen durch zuerst teilen und dann multiplizieren

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

int main() 
{ 
double x, mySin(), myCos(), myExp(); 
char more; 

do  { 
    printf ("\n\t\t\t\t\tInput x: "); 
    scanf ("%lf", &x); 
    printf ("\n\t\t\t\t\t\t\tLibraryResult \t MyResult"); 
    printf ("\n\t\t\tSin(%6.2f)\t  %9.6f\t\t%9.6f", x, sin(x), mySin(x)); 
    printf ("\n\t\t\tCos(%6.2f)\t  %9.6f\t\t%9.6f", x, cos(x), myCos(x)); 
    printf ("\n\t\t\tExp(%6.2f)\t  %9.6f\t\t%9.6f", x, exp(x), myExp(x)); 
    printf ("\n\n\t\t\t\t\tDo more (Y/N) ?"); 
    scanf ("%s", &more); 
} while (more == 'y' || more == 'Y'); 
} 

double mySin(double x) 
{ 
double sum = 0., divide(); 
int i, sign = 1; 

for (i = 0; i < 30; i++, sign = - sign) 
    sum = sum + sign * divide(x) ; //power(x, 2 * i + 1)/fact(2 * i + 1); 

return sum; 
} 

double myCos(double x) 
{ 
double sum = 0., divide(); 
int i, sign = 1; 

for (i = 0; i < 30; i++, sign = - sign) 
    sum = sum + sign * divide(x);//power(x, 2 * i)/fact(2 * i); 

return sum; 

} 

double myExp(double x) 
{ 
double sum = 0., divide(); 
int i; 

for (i= 0; i < 30; i++) 
    sum = sum + divide(x); //power(x, i)/fact(i); 


return sum; 
} 


double divide(int n, double x) 
{ 
int i; 
double div = 1.; 

for (i = 1; i < n; i++) 
    div = x/i; 

return div; 

} 

/*double fact(int n) 
{ 
int i; 
double prod = 1.; 

for (i = 1; i <= n; i++) 
    prod = prod * i; 

return prod; 
} 

double power (double x, int n) 
{ 
int i; 
double prod = 1.; 

for (i = 0; i < n; i++) 
    prod = prod * x; 

return prod; 
} 
*/ 

Ich habe mit dem Code und, wenn in dem Divide() Herumspiele, i < n ergibt kein Ergebnis zu verwenden, wenn I x einzugeben. Allerdings funktioniert die Verwendung von i < 30, aber die Berechnungen sind falsch. Ich versuche das herauszufinden, also wäre nur ein Zeiger hilfreich! Vielen Dank!

+0

In der Divide-Funktion macht die 'for'-Schleife nichts, weil Sie einfach den Wert von' div' jedes Mal überschreiben. Also, so wie es ist, ist die Funktion äquivalent zu 'return x/(n-1);'. Vielleicht meintest du 'div * = x/i;'. – user3386109

+2

Beachten Sie auch, dass Ihre 'divide' zwei Argumente benötigt:' dividiere (int n, double x) ', aber du nennst es mit nur einer,' sum = sum + sign * divide (x) '. Dies sollte Ihnen einen Fehler geben, aber Sie haben eine 'lokale' Division als 'doppelte Summe = 0, dividieren();' erklärt, mit der der Compiler nur einverstanden ist, aber dann geben Sie nur x an, damit es keine Ahnung hat, was zu tun ist mach mit n. Übergeben Sie das Extra 'n' und es sollte mehr Sinn ergeben. – LambdaBeta

+0

Allgemeiner Tipp, um das Problem zu vermeiden, auf das LambdaBeta hingewiesen hat: Stellen Sie niemals Funktionsprototypen in andere Funktionen und niemals unter Angabe eines Funktionsprototyps. Es gibt zwei Standardverfahren. 1) Setzen Sie alle Funktionsprototypen an den Anfang der Datei. Kopieren Sie die Funktionsdefinition, fügen Sie sie am Anfang der Datei ein und fügen Sie ein Semikolon hinzu. 2) Ordnen Sie die Funktionen in umgekehrter Reihenfolge an. Das heißt, divide steht zuerst in der Datei, gefolgt von myCos, mySin, myExp und main am Ende der Datei. Auf diese Weise fungieren die Funktionsdefinitionen als Funktionsprototypen und vermeiden Fehler in den Prototypen. – user3386109

Antwort

1

Ich dachte, ich würde Ihnen eine Antwort geben, da Ihr Problem systemisch ist.

Ziehen Sie zuerst die Funktionen in Forward-Deklarationen. Nicht mehr:

double x, mySin(), myCos(), myExp(); 

diese Statt über int main() setzen:

double divide(int n, double x); 
double mySin(double x); 
double myCos(double x); 
double myExp(double x); 

Dies bietet Ihnen auch eine große Chance, zu dokumentieren, was diese tun. Dies wird Ihr Problem tatsächlich lösen! (Ja, auch wenn die Dokumentation ist nur ein Kommentar):

// Returns x^n/n! 
double divide(int n, double x); 

zu diesem Kommentar Sehen, plötzlich mySin macht keinen Sinn:

sum = sum + sign * divide(x); // this is sum += sign * x^?/?! 

So Mysin Korrektur wie folgt aussehen würde: (Bem dass Ziehen Logik der Schleifenanweisung aus ist in der Regel eine gute Idee)

// The series for sin(x) starts with x^1/1 and continues by increasing by 2 
for (i = 1; i < 30; i += 2) { 
    sum += sign * divide(i,x); // += saves you from writing sum + ... 
    sign = -sign; 
} 

Dies sollte die korrekte Ausgabe produzieren, aber es funktioniert nicht. Leider hast du auch ein Problem in deinem divide(). Keeping seine Dokumentation im Auge, läßt es einen Blick:

double divide(int n, double x) 
{ 
int i; 
double div = 1.; 

for (i = 1; i < n; i++) 
    div = x/i; 

return div; 

} 

Dies ist ganz in der Nähe zu korrigieren, es ist nur, dass die Gleichheitszeichen ist nicht ganz richtig. Wir wollen jede Iteration mit x/i multiplizieren.

for (i = 1; i < n; i++) 
    div *= x/i; 

Ist viel näher, aber lassen Sie zählen, wie oft diese Schleife wird. Es ist n-1 mal (wenn wir bei 0 angefangen hätten, wäre es n mal, aber wir hätten eine Division durch 0 Fehler). Lassen Sie uns das in Ordnung bringen:

for (i = 1; i <= n; i++) 
    div *= x/i; 

Nun ist diese technisch Teilung zugleich als Multiplikation tun wird, was die genauesten Ergebnisse produzieren (von div-in der Nähe von ‚normalen‘ Zahlen zu halten). Wenn Sie zuerst teilen, werden Sie anfangen, wirklich kleine Zahlen zu verwenden, und wenn Sie zuerst multiplizieren, beginnen Sie, wirklich große Zahlen zu verwenden. In jedem Fall werden Sie die Genauigkeit verlieren (da die Doppelnummern bei mittelgroßen Zahlen am genauesten sind).Wenn Sie das tun aufgeteilt, dass Schleife auseinander hinein dreht:

divide Schleife:

for (i = 1; i <= n; i++) 
    div /= i; 

mehrfach Schleife:

for (i = 1; i <= n; i++) 
    div *= x; 

Für die meisten Eingänge, wird es nicht viel Unterschied machen, überhaupt . Wenn Sie jedoch "extreme" Werte haben, werden Sie am Ende Ihre Doppelgänger töten. Wenn Sie beispielsweise zuerst multiplizieren, wenn Sie x = 1000 verwenden, werden Sie das Leerzeichen des Double überschreiten, bevor Sie tatsächlich beginnen, zu teilen. Das Ergebnis wird nan sein, da das Double nicht damit umgehen kann. Ähnlich, wenn Sie die Iterationen aufpumpen (statt 30, tun 30000000), wird es natürlich viel länger dauern (etwa 100000 mal länger natürlich), aber wenn Sie auch zuerst teilen, enden Sie damit, Ihr Double auf Null zu setzen, bevor Sie zu multiplizieren . Als solche erhalten Sie ein Ergebnis von 0 (Hinweis: Ich habe das nicht getestet, das ist Theorie). Es ist auch durchaus möglich, dass der Compiler die Optimierungsmöglichkeit sieht und für Sie übernimmt.

Verwandte Themen