Προς το περιεχόμενο

Σειρά Taylor (sin,cos) ANSI C


Bill_P

Προτεινόμενες αναρτήσεις

10 λεπτά πριν, albNik είπε

Όπως είπα δεν έχει νόημα για x>2*3.14 διότι επαναλαμβάνεται.

 Αλλά και για x=6 μετά από σχετικά λίγους όρους σταθεροποιείται και το σφάλμα είναι αμελητεο.

(6^17)/17! = 0.04...

(6^19)/19! = 0.005...

(6^21)/21! = 0.00004...

Δεν έχουν καμιά σχέση αυτά που γράφεις.
Το cancellation error το έχεις ακούσει ποτέ;  διότι περί αυτού πρόκειται.

-

 

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Ε καλά, εσύ χρησιμοποίησε τέτοιες σειρές για αριθμητικές πράξεις.
Aν δεν καταλαβαίνεις την ουσία του προβλήματος εγώ θα σου αλλάξω μυαλά;
Κακό του κεφαλιού σου...

-

 

 

 

 

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Φαίνεται πως καθε όρος προσθέτει 0.6~~~~ στο range που μπορει να παρει το χ. Απο περιέργεια θα γραψω ενα σκριπτακι για να δω αν ειναι γραμμική αυτη η σχεση.Screenshot_2018-12-31-19-04-04.png.2df0c98a326ac0f7bf2601c0b605182a.png

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Το πρόβλημά σου είναι καταρχάς θεωρητικό και δεν είναι θέμα "σοβαρού προγραμματιστή" όπως αναφέρθηκε. Όταν θέλουμε να υπολογίσουμε μία  σειρά Taylor με πεπερασμένους όρους, τότε πρέπει να δεχθούμε ότι οι υπολογισμοί μας οφείλουν να βρίσκονται κοντά στο κέντρο xo (στην περίπτωσή σου για lim x -> 0). 

Ουσιαστικά η σειρά Taylor (McLaurin για την ακρίβεια) που έχεις πάρει για το ημίτονο δεν συγκλίνει γρήγορα για μεγάλα x. 

Το καταστροφικό σφάλμα (cancellation error) που ανέφερε κάποιος, ισχύει μεν, αλλά δεν είναι η αιτία που "σου φεύγει" η ακριβής τιμή στον υπολογισμό όσο αυξάνεις όρους. Αυτό οφείλεται στο φαινόμενο Runge.  

Πρέπει να βρεις μια άλλη προσέγγιση της συνάρτησης sinx για μεγαλύτερα x. Απαξ και το κάνεις αυτό, μετά μπορείς να εφαρμόσεις μεθόδους για να μειώσεις το σημαντικό σου σφάλμα (significance error).

Ρίξε μια ματιά εδώ, σε έναν κλασικό αλγόριθμο υπολογισμού τριγωνομετρικών συναρτήσεων.

 

Καλή Χρονιά.

  • Like 2
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δημοσ. (επεξεργασμένο)

O αλγόριθμος CORDIC, ο οποίος παρεμπιπτόντως μελετάται ενδελεχώς στο βιβλίο του J. Muller "Elementary Functions. Algorithms and Implementation", κεφ. 7,
δεν είναι τετριμμένη γνώση για έναν προγραμματιστή. Ούτε είναι αλγόριθμος που θα επιχειρούσε να υλοποιήσει κάποιος καθώς είναι εξαιρετικά πολύπλοκος,
σε σύγκριση με ένα "απλό" άθροισμα σειράς.

Αντίθετα, το σφάλμα ακύρωσης είναι κοινοτοπία και πρέπει να το ξέρουν όλοι.
Είναι το σφάλμα που σχεδόν πάντα προξενεί τη μεγαλύτερη ζημιά και εφιστάται η προσοχή στη χρήση θεωρητικών σχέσεων.
Εν προκειμένω, η προσθαφαίρεση όρων στις σειρές δημιουργεί μεγάλη ανακρίβεια για μεγάλα x, (περίπου x>3),
και κύρια αυτό είναι που καταστρέφει την αριθμητική σύγκλιση. Η χρήση διπλής ακρίβειας μειώνει τη ζημιά αλλά όχι πάντα.
Σε "δύσκολες" συναρτήσεις όπως οι Bessel η σωστή χρήση των σειρών και αναδρομικών σχέσεων απαιτεί μεγάλη μαεστρία
ο στόχος είναι η σχέση να δουλεύει πάντα χωρίς προβλήματα και να μην ξεφεύγει ανάλογα με το όρισμα ή την τάξη της συνάρτησης.

Οι σχέσεις προσέγγισης από τα πολυώνυμα είναι εγγυημένο ότι δεν έχουν πρόβλήματα,
όμως πρέπει να μεταγράφεται κατάλληλα το όρισμα όταν είναι έξω από το διάστημα που ισχύουν (συνήθως [0,π/2]).

Για δε το φαινόμενο Runge ο φίλος φίλος έχει δίκιο, το είχα ξεχάσει.


-

 

Επεξ/σία από V.I.Smirnov
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δημοσ. (επεξεργασμένο)

Αν προσέξεις τους αριθμούς θα δεις ότι είναι απλά arithmetic series το 1ο με α1=1 και δ=2 το 2ο με α1=0 και δ=2 η αλλαγή του προσιμου στο 1ο series είναι (-1)^(n+1) ενώ στη 2 (-1)^n Οπότε έχεις για το 1ο Σ (-1)^(n+1)x^(2n-1)/(2n-1)! Το 2ο θα το βρεις

Καλή Χρόνια

Επεξ/σία από k33theod
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Αυτά που λέτε εννοείται πως είναι σωστά αλλά αφενός είναι λίγο overkill να μιλάμε για ακρίβεια σε αυτή την άσκηση που ο καθηγητής θα δοκιμάσει τιμές 0, 30, 45, 90 και ούτε καν αυτές, αφετέρου the voice of god (εκφώνηση) ζητάει να λυθεί με αυτούς τους τύπους οπότε πρέπει να λυθεί έτσι και όχι με την σούπερ ντούπερ καλύτερη συνάρτηση που έχει τέλεια ακρίβεια.

Bill_P μικρούς μας έβαζαν στο μάθημα της έκθεσης να γράψουμε ένα σκελετό αυτών που θέλουμε να γράψουμε ώστε να μας είναι πιο εύκολο να τα σχεδιάσουμε στο μυαλό μας. Κάνε το ίδιο πράγμα και σκέψου τι  πρέπει να κάνεις. Με έναν τέτοιο συλλογισμό θα έχεις κάθε φορά να κάνεις ένα μικρό βήμα οπότε δεν θα χαθείς.

Βήμα 1: Θα εμφανίσω μήνυμα στον χρήστη να μου δώσει μια τιμή ενημερώνοντας τον ότι πρέπει να είναι σε μοίρες.

Βήμα 2: Όλες οι συναρτήσεις μου δουλεύουν με ακτίνια οπότε πρέπει να χρησιμοποιήσω κάποιον τύπο για να μετατρέψω τις μοίρες.

κτλ.

Οι τύποι με την μορφή που έχουν ίσως σε μπερδεύουν και δεν μπορείς να τους μετατρέψεις εύκολα σε κάποιο for βρόχο. Έτσι λοιπόν μπορείς να τους μετατρέψεις σε μια πιο "εύκολη" μορφή. Εννοείται πως θα βρεις τους τύπους σε βιβλία αλλά δεν είναι δύσκολο να το κάνεις με το μυαλό σου. Για το ημίτονο έχεις 1, 3, 5, 7, 9, κτλ οπότε πώς μπορείς να το γράψεις αυτό; Ξεκινάς από τη μονάδα και κάθε φορά προσθέτεις 2 οπότε 1 + 2n. Το μόνο που μένει τώρα είναι ότι το πρόσημο εναλλάσσεται οπότε πώς θα το γράψεις αυτό; Ένας αρνητικός αριθμός υψωμένος σε ζυγή δύναμη δίνει θετικό αποτέλεσμα και αρνητικό αποτέλεσμα όταν υψώνεται σε μονή δύναμη, οπότε το κάνεις (-1) ^ n. Έτσι λοιπόν ο τύπος γίνεται sin(x) = Σ (-1) ^ n  * x ^ (2n + 1) / (2n+1) ! με το n να ξεκινά από το 0 και να πηγαίνει μέχρι όσους όρους θέλεις. Αυτό τώρα είναι εύκολο να το κάνεις με βρόχο. Ομοίως και για το συνημίτονο.

Εμφάνισε "Δώσε γωνία σε μοίρες"
Λάβε μεταβλητή Θμ
Θα = Θμ * π / 180 για να γίνει ακτίνια

Κάλεσε τις έτοιμες συναρτήσεις της C και έπειτα
Εμφάνισε "Με τις συναρτήσεις τις C έχουμε sin = τόσο, cos = τόσο"

Κάλεσε τις δικές σου συναρτήσεις και έπειτα
Εμφάνισε "Με σειρές Taylor έχουμε sin = τόσο2, cos = τόσο2"

Υποπρογράμματα που θα γράψεις εσύ:
factorial
mysin
mycos

παράδειγμα mysin (μεταβλητή χ σε ακτίνια)
Επανάληψη από i = 0 μέχρι πχ 10 κάνε
    myx = x υψωμένο στην δύναμη 2*i+1
    myfact = κλήση δικής μου συνάρτησης factorial(2*i+1)
    mysin = mysin + (-1) ^ i * myx / myfact
Όταν τελειώσει η επανάληψη, η μεταβλητή mysin έχει τιμή το ημίτονο.

Αυτή η μορφή βέβαια που ζητάει η άσκηση κάνει άπειρους περιττούς υπολογισμούς και θα μπορούσε να απλοποιηθεί πάρα πολύ αλλά αυτό είναι άλλο κεφάλαιο.

  • Like 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Καλησπέρα, παιδιά !

Μόλις έγραψα ένα κομματάκι κώδικα που κάνει αυτό που ζητάει ο φίλος μας. Όπως θα δείτε, το έχω σκαρώσει αρκετά βιαστικά και δεν ξέρω αν υπάρχει κανένα κρυμμένο bug πουθενά.
 Το πρόγραμμα ζητάει αρχικά μια γωνία σε μοίρες και τη μετατρέπει σε ακτίνια μέσω της συνάρτησης degtorad.  Έπειτα ζητάει να ορίσουμε πόσο «μακριά» θα πάει το άθροισμα Taylor, δηλαδή πόσοι είναι οι όροι που θα συμπεριληφθούν στο άθροισμα.
Επειδή το σημείο σύγκλισης είναι το x=0 εδώ έχουμε μια ειδική περίπτωση του αναπτύγματος Taylor που λέγεται ανάπτυγμα Maclaurin.
Οι συναρτήσεις power και factorial αντίστοιχα υλοποιούν την ύψωση σε δύναμη και τον υπολογισμό του παραγοντικού. Η συνάρτηση elim_angle αντιστοιχίζει τη δεδομένη γωνία στο διάστημα [0,2π] όπως θα δείτε. Τέλος υπολογίζεται και τυπώνεται στην οθόνη το ημίτονο και το συνημίτονο της δεδομένης γωνίας. Ο κώδικας έχει ως εξής :

 

#include <stdio.h>
#include <math.h>
long int factorial(int n) {
int result=1,x=n;
if ((n==0)||(n==1)) return 1;
for(x=n;x>=1;x--) result*=x;
return result;
}
double power(double b, int e) {
double result=1; int q=0;
if(e==0) return 1;
if(e==1) return b;
for(q=1;q<=e;q++) result*=b;
return result;
}
double degtorad(double angle) { return angle*M_PI/180; }
double elim_angle(double angle) {
double tmp=angle;
while(tmp>=2*M_PI) tmp-=2*M_PI;
return tmp;
}
double maclaurin_sine(double angle,int n) {
int x=0; double final_sum=0;
if(angle>=0) {
double new_angle=elim_angle(angle);
if(new_angle>M_PI/2) new_angle=M_PI-new_angle;
for(x=0;x<=n;x++)
{
 double a=power(-1,x);
 double f=power(new_angle,2*x+1);
 long p=factorial(2*x+1);
 final_sum+=a*f/p; }
return final_sum; }
else {
double new_angle=elim_angle((-1)*angle);
if(new_angle>M_PI/2) new_angle=M_PI-new_angle;
for(x=0;x<=n;x++) {
double a=power(-1,x);
double f=power(new_angle,2*x+1);
long p=factorial(2*x+1);
final_sum+=a*f/p; }
return (-1)*final_sum; }
}
double maclaurin_cosine(double angle,int n) {
double comp_angle=M_PI/2-angle;
return maclaurin_sine(comp_angle,n);
}
void main()
{
double angle=0; int n=0;
printf("Dwste mia gonia se moires ");
scanf("%lf",&angle);
printf("Posous orous theleis na prostheso ?");
scanf("%d",&n);
angle=degtorad(angle);
printf("\n\n");
printf("To imitono einai %.2lf\n",maclaurin_sine(angle,n));
printf("To sinimitono einai %.2lf\n",maclaurin_cosine(angle,n));
}

Καλή χρονιά να έχουμε, κυρίως υγεία,
Μ' ένα εγκάρδιο νιαούρισμα,
Ο Άσπρος Γάτος

Υ.Γ : Συγνώμη για τα Greeklish μέσα στη main, αλλά έγραψα τον κώδικα σε σκέτη μαύρη οθόνη Unix όπου τα Ελληνικά δεν τα βγάζει καλά. Άμα νομίζουν οι Sysops, παρακαλώ να μην μου το σβήσουν το μήνυμα.

 

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα
  • Δημιουργία νέου...