Ellipsenumfangberechnung - Fehler?



  • Hey, hab ein Programm für die Uni geschrieben, dass mir den Umfang einer Ellipse näherungsweise berechnet. Dabei wird die Ellipse in n Geradenstücke aufgeteilt, dessen Länge bestimmt und am Ende zum Umfang aufsummiert.
    Nun ist es so, dass ab einem bestimmten Wert u0 auf einmal größer ist als u1, was aber nach logischer Betrachtung eigentlich nicht sein dürfte (wegen Annäherung).
    Eingegeben werden die Halbachsen a und b, sowie der relative Fehler ((x1-x0)/x1).
    Das Programm soll stoppen, sobald entweder n = 2^24 erreicht ist, oder der rel. Fehler (Ist) kleiner ist als der rel. Fehler (Soll, bzw. Eingabe).

    #include <stdio.h>
    #include <math.h>
    
    double laenge(double x1, double  y1, double  x2, double  y2)
    {
      return sqrt((y2-y1) * (y2-y1) + (x1-x2) * (x1-x2));	//Länge über Pythagoras
    }
    
    void ellipse(double a, double  b, double  t, double* x, double* y)	//Koordinaten der Punkte
    {
      *x = a * cos(t);
      *y = b * sin(t);
    }
    
    int main(void)
    {
      double a, b, t,	//Längen und Abschnittsparameter
    	 x1, y1, x2, y2,//Koordinaten
    	 u0, u1,	//Umfang n und Umfang n*2
    	 e, eps;	//rel. Fehler (Ist), rel. Fehler (Soll)
      int n, n0;		//n in 1. Quadrant; n0 gesamt
    
      printf("Halbachsen a und b eingeben: ");
      scanf("%lf %lf", &a, &b);
      printf("Relativen Fehler e eingeben: ");
      scanf("%lf", &e);
    
      for(n = 4, n0 = 4, eps = 1; n <= (64*64*64*64) /*&& e <= eps*/ ; n0 *= 2)	//bis e <= eps oder n = 2^24; n0 wird verdoppelt
      {
        n = n0 / 4;	//Umfang >> u0 << bei n/4 Geradenstücke
        for(t = 0, u0 = 0; t < M_PI / 2; t += (M_PI / 2) / n)
        {
          ellipse(a, b, t, &x1, &y1);		//P1
          ellipse(a, b, t + (M_PI / 2) / n, &x2, &y2);//P2
    
          u0 += laenge(x1, y1, x2, y2);  //Aufsummation  
        }
    
        n = n0 / 2;	//Umfang >> u1 << bei n/2 Geradenstücke
        for(t = 0, u1 = 0; t < M_PI / 2; t += (M_PI / 2) / n)
        {
          ellipse(a, b, t, &x1, &y1);		//P1
          ellipse(a, b, t + (M_PI / 2) / n, &x2, &y2);//P2
    
          u1 += laenge(x1, y1, x2, y2); //Aufsummation
        }
    
        u0 *= 4;
        u1 *= 4;
    
        eps = (u1 - u0) / u1;	//Gemäß (x1 - x0) / x1
        printf("U0 = %.15lf\n", u0);
        printf("U1 = %.15lf\n\n", u1);
      }
      printf("Umfang = %.15lf\n", u0);
      printf("Relativer Fehler = %.25lf\n", eps);
      printf("n = %i\n", n);
    
      return 0;
    }
    

    u0 ist der Umfang bei n/4 und u1 bei n/2 .
    Die Längen werden nur für den ersten Quadranten berechnet (Symmetrie) und zum Schluss mit 4 multipliziert.

    Hier ein Teil der Ausgabe (Diese Ausgabe wurde aus dem obigen Code wieder entfernt, war nur zur Überprüfung gedacht) für n = 16 bis n = 512:

    U0 = 45.732250080830433
    U1 = 45.952325632195659
    
    U0 = 45.952325632195659
    U1 = 46.007743505572165
    
    U0 = 46.007743505572165
    U1 = 46.021604352373600
    
    U0 = 46.021604352373600
    U1 = 47.006730924295546
    
    U0 = 47.006730924295546
    U1 = 46.516799390660779
    
    U0 = 46.516799390660779
    U1 = 46.271588559358030
    

    Hat jmd ne Idee, warum auf einmal U0 größer ist als U1?

    MfG



  • Durch Rundungsfehler bei der Berechnung von t.

    Du hast da dann nicht 64 Durchläufe sondern 63.
    Und da du nur ein Viertel berechnest, vervierfacht sich der Fehler.

    Zähle die Durchläufe (du willst ja n haben) und bereche t jedesmal neu

    t = i * ((M_PI / 2) / n)
    


  • Top, danke!
    Hat was gebracht, nur leider setzt dasselbe Problem nun etwas später bei genaueren Werten ein. Ich denke mal aufgrund der Aufsummierung des Umfangs:

    for(t = 0, i = 0, u0 = 0; t < M_PI / 2; t = i * (M_PI / 2) / n)
        {
          ellipse(a, b, t, &x1, &y1);		//P1
          ellipse(a, b, t + (M_PI / 2) / n, &x2, &y2);//P2
    
          u0 += laenge(x1, y1, x2, y2);  //Aufsummation  
    
          ++i;
        }
    

    oder? Aber die kann ich ja schlecht als Produkt berechnen, ist ja im Endeffekt näherungsweise ein Integral... long double hab ich auch schon versucht^^



  • DirkB schrieb:

    Zähle die Durchläufe (du willst ja n haben) ...

    Du musst i überprüfen, nicht t.

    for(i = 0, t = 0, u0 = 0; i < n ; ++i)
        { t = i * (M_PI / 2) / n
          ellipse(a, b, t, &x1, &y1);       //P1
          ellipse(a, b, t + (M_PI / 2) / n, &x2, &y2);//P2
    
          u0 += laenge(x1, y1, x2, y2);  //Aufsummation  
    
        }
    


  • Hm das macht nun auch keinen Unterschied zu der Schleife, die ich oben hatte... Ausgabe sieht so aus (mit rel. Fehler für jedes n):

    eps = 0.041713584569423
    eps = 0.016960237953730
    eps = 0.004789214655352
    eps = 0.001204533610082
    eps = 0.000301181303792
    eps = 0.000075298160853
    eps = 0.000018824717399
    eps = 0.000004706190423
    eps = 0.000001176548315
    eps = 0.000000294137095
    eps = 0.000000073534333
    eps = 0.000000018383606
    eps = 0.000000004595637
    eps = 0.000000001149343
    eps = 0.000000000286451
    eps = 0.000000000071172
    eps = 0.000000000017731
    eps = 0.000000000004377
    eps = 0.000000000018650
    eps = -0.000000000022917
    eps = -0.000000000019566
    eps = -0.000000000006715
    eps = 0.000000000278440
    Umfang = 46.026225189782515
    Relativer Fehler = 0.000000000278440
    n = 16777216
    

Anmelden zum Antworten