Série Taylor Extension de cos x et sin x en C Programmation sans utiliser math.h et uniquement à l’intérieur de int main ()

Je travaille sur un projet pour notre école et nous devons créer un programme qui calcule l’approximation de la série d’expansion de Taylor de sin x et cos x , uniquement à l’aide de et sans fonctions définies par l’utilisateur autres que int main() , de tous les angles de -180 à 180 par incréments de +5 . Voici mon code:

 #include  #define PI 3.141592653589 #define NUMBER_OF_TERMS 10 int main() { int cosctr, sinctr; double ctr, radi; double cosaccu, costerm, sinaccu, sinterm; for (ctr = -180; ctr < 185; ctr = ctr + 5) { radi = ctr * PI/180.0; cosctr = 1; cosaccu = 1; costerm = 1; sinctr = 2; sinaccu = radi; sinterm = radi; while (cosctr <= 2*NUMBER_OF_TERMS) { costerm = costerm*(-1)*(radi*radi)/(cosctr*(cosctr + 1)); cosaccu = cosaccu + costerm; cosctr+=2; } do { sinterm = sinterm*(-1)*(radi*radi)/(sinctr*(sinctr + 1)); sinaccu = sinaccu + sinterm; sinctr+=2; } while (sinctr <= 2*NUMBER_OF_TERMS); printf("%.2lf %.12lf %.12lf %.12lf\n", ctr, radi, cosaccu, sinaccu); } return 0; } 

Le code ci-dessus est exact pour une approximation d’expansion de 15 termes. Cependant, si je modifie NUMBER_OF_TERMS en 5 ou 10, par exemple, l’approximation est erronée.
Aucune suggestion?

Permettez-moi de préciser: je dois obtenir une approximation de 5 termes, 10 termes et 15 termes. Je ne peux utiliser aucune autre bibliothèque que . Je ne peux utiliser aucune autre fonction en dehors de int main() (je m’excuse du manque de précision de mes explications auparavant).
S’il vous plaît répondre avec le code corrigé inclus.

La clé de la précession élevée, mais le calcul simple de sind(degrees) et cosd(degrees) consiste à réduire la plage de degrés à 0 à 90 (voire 0 à 45) en utilisant les ajustements sortinggonomésortingques usuels avec des arrangements de degrés .

Réductions
angle = fmod(angle, 360) // réduire (-360..360) ou utiliser a = a – (int) (a / 360)
sin(x) = -sin(-x) // réduire à [0..360)
cos(x) = cos(-x) // réduit à [0..360)
sin(x) = -sin(x-180) // réduire à [0..180)
cos(x) = -cos(x-180) // réduire à [0..180)
sin(x) = cos(90-x) // réduire à [0..90)
Réductions supplémentaires:
Pour [45-90), utilisez sin(x) = cos(90-x) // réduit à [0..45)

puis convertir en radians et utiliser le développement en série de Taylor.

Exemple

Remarque: Étant donné que le code traite avec double précision double , généralement de 17 chiffres, il n’est pas nécessaire d’utiliser une approximation d’IP de cours.

 // #define PI 3.141592653589 #define PI 3.1415926535897932384626433832795 

J’ai essayé votre code; cela fonctionne bien pour moi, en ce sens qu’il fait ce à quoi il a été conçu. Voici une comparaison entre la sortie de votre code pour le cosinus à 5 et 10 termes et la même approximation calculée par Mathematica. Ils s’accordent jusqu’à <10^-12 , c’est-à-dire votre précision sortie .:

entrez la description de l'image ici

Le seul problème que je vois dans votre code est que, dans la façon dont vous avez conçu vos boucles, vous prenez en compte NUMBER_OF_TERMS + 1 si vous comptez les premiers termes de l’expansion (c.-à-d. Le terme constant pour le cosinus, le linéaire terme pour le sinus.) Vous commencez par ce premier terme, puis votre boucle ajoute un autre terme NUMMBER_OF_TERMS . Si ce n'est pas intentionnel, vous vous approchez des fonctions avec une précision supérieure à celle que vous attendez.

Par sa définition même, une série de Taylor est la sum d’une série infinie de termes.

Ainsi, une expansion finie de Taylor uniquement est une approximation du résultat vrai: plus le nombre de termes est élevé, plus la précision de cette approximation est grande.

S’il y a suffisamment de termes, l’erreur d’approximation devient à un moment donné imperceptible. Toutefois, si vous essayez de réduire le nombre de termes, l’erreur d’approximation augmente et peut être détectée.

Dans votre cas, l’erreur d’approximation est inférieure au seuil de détection de NUMBER_OF_TERMS = 15, mais devient perceptible lorsque NUMBER_OF_TERMS = 10 ou moins.

Les expansions de Taylor de sin (x) et de cos (x) mettent plus de temps à converger lorsque x augmente. Mais comme il s’agit de fonctions périodiques, il n’est pas nécessaire de développer les séries pour des valeurs situées en dehors de la plage 0-90 °.

Pour les valeurs de x situées en dehors de cette plage, utilisez les identités suivantes:

 sin(x) = -sin(x+180°) = -sin(-x) = sin(180°-x) cos(x) = -cos(x+180°) = cos(-x) = -cos(180°-x) 

Par exemple, sin (175 °) = sin (5 °), cos (-120 °) = -cos (60 °)

Je l’ai compris avec l’aide d’un autre utilisateur. s’avère que j’étais en train de calculer les termes + 1, ce qui rend la réponse plus précise que prévu. après 15 termes, les changements ont dépassé la 12e décimale et ne sont donc pas affichés dans les résultats.

 #include  #define PI 3.141592653589 #define NUMBER_OF_TERMS 10 // 5 and 15 work as well int main() { int cosctr, sinctr; double ctr, radi; double cosaccu, costerm, sinaccu, sinterm; // accu will be final answer, term will be added to accu for (ctr = -180; ctr < 185; ctr+=5) { // for loop; ctr initialized at -185 and added to in increments of 5 to produce degrees radi = ctr * PI/180.0; // calculation for radians (assigned to radi) cosctr = 1; // initialization for cos counter; must be included in loop to allow correct calculations of cos cosaccu = 1; // first term is 1 costerm = 1; // base term, to be multiplied with termcalc formula sinctr = 2; // initialization for sin counter; must be included in loop to allow correct calculations of sin sinaccu = radi; // first term is x, or degrees in radians (radi) sinterm = radi; // base term for sin // cos calculation while (cosctr < 2*NUMBER_OF_TERMS-1) { // accuracy check, 2* since increments of 2; NOTE: actual values are (1, 3, 5,...) costerm = costerm*(-1)*(radi*radi)/(cosctr*(cosctr + 1)); // TERMCALC FORMULA; multiplying previous term with formula creates next term cosaccu = cosaccu + costerm; // addition of new term to previous sum; dependent on accuracy (NUMBER_OF_TERMS) cosctr+=2; } do { // sin calculation; identical to cos, albeit with substituted vars sinterm = sinterm*(-1)*(radi*radi)/(sinctr*(sinctr + 1)); sinaccu = sinaccu + sinterm; sinctr+=2; } while (sinctr < 2*NUMBER_OF_TERMS-1); // accuracy check, 2* since increments of 2; NOTE: actual values are (2, 4, 6,...) printf("%.2lf\t%.12lf\t%.12lf\t%.12lf\n", ctr, radi, cosaccu, sinaccu); // final display; /t used for convenience } return 0; // finally!!! }