Tiefe eines Brunnens

  • Hi.
    ich melde mich wieder mit der neuen Aufgabe zur Diskusion.


    Die Tiefe eines Schachts oder Brunnen können wir in Kurzer Zeit errechnen, wenn wir einen Stein hinunterfallen lassen und die Zeitspanne vom Loslassen des Steins bis zum Eintrefen des Schalls nach dem Aufprall möglichst genau messen.
    Berechnung durch Iteration.
    Zu erst Rechnung von der Schachttiefe ohne Berücktsichtigung der Schallgeschwindigkeit nach der Formel :
    s1=(t*t*a)/2
    hierhin bedeuten:
    s1-Tiefe ohne Berücksichtigung der Schallgeschwindigkeit
    t - gemessene Zeit
    a - Erdbeschleunigung=9,81 m/sec²
    Anschließend ermittelt unser Programm, wie lange der Schall auf der errechneten Strecke unterwegs gewesen wäre. Diese Zeit ergibt sich aus der Formel:
    ts = s1/V
    ts = Zeit für den Schall
    s1 = Tiefe ohne Berücksichtigung des Schalls
    V = Schallgeschwindigkeit
    Aufgabe:
    Statt Iterationsberechnung ( Im Menü unter Case 'I' aufgefürt)- Rekursionfunktion -"reursion() "anwenden !!!
    /***********************************************************************/
    /* ue_06 Berechnung der Tiefe eines Schachtes aus der Zeit */
    /* zwischen dem Loslassen eines Steins und dem Eintreffen */
    /* des Schalls nach Aufschlag des Steins. Die Berechnung */
    /* erfolgt: a) Mit Hilfe der exakten Loesungsformel. */
    /* b) Mittels Iteration. */
    /***********************************************************************/


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


    #define SCHALL 330.0 /* Schallgeschwindigkeit 330 m/s. */
    #define ERDBESCHL 9.81 /* Erdbeschleunigung 9.81 m/(s^2).*/
    #define ABWEICHUNG 0.001 /* zugel. Abweichung bei Iteration*/
    #define BIL clear(); /* Bildschirm loeschen */
    #define ROW 4 /* erste Ausgabezeile */
    #define COL 10 /* Ausgabespalte */
    #define RETURN 13


    void wait(void);


    void main(void)
    {
    char kennbuchst;
    double zeit,zeit2; /* Gesamtzeit in Sekunden. */
    double tiefe,tiefe1,tiefe2; /* Tiefe des Brunnens in Meter. */
    double diff, x, y; /* Hilfsvariablen */
    int i;
    char str[100];
    initscr(); /* Initialisiert das Terminal */
    cbreak(); /* Zeichen sofort weiterreichen */
    nonl(); /* Keine neue Zeile bei Return */
    intrflush(stdscr, FALSE);
    keypad(stdscr, TRUE); /* Ziffernblock aktivieren. */
    clear(); /* Bildschirm loeschen */
    do /* Beginn der do-while-Schleife */
    {
    BIL;
    mvaddstr(ROW,COL," L Berechnen der Tiefe mit der Loesungsformel");


    mvaddstr(ROW+2,COL," I Berechnen der Tiefe mittels Iteration");


    mvaddstr(ROW+4,COL," T Ausgeben einer Tabelle ");


    mvaddstr(ROW+6,COL," x Programm beenden");


    mvaddstr(ROW+8,COL," Programmfortsetzung: ");
    kennbuchst = getch();
    BIL;
    switch(kennbuchst)
    {
    case 'l': /* Berechnen der Tiefe nach Eingabe */
    case 'L': /* der gemessenen Zeit */
    addstr("\n\n\n\t\t Zeit vom Loslassen des Steins bis zum ");
    addstr("\n\t\t Eintreffen des Schalls in Sekunden : ");
    addstr("\n\t\t ");
    getstr(str);
    sscanf(str,"%lf",&zeit);
    x = zeit/SCHALL + 1.0/ERDBESCHL;
    y = zeit/SCHALL;
    tiefe = (double)(SCHALL * SCHALL * ( x - (x * x - y * y )));


    sprintf(str,"\n\n\t\t Der Schacht ist %5.1f Meter tief",tiefe);
    addstr(str);
    wait();
    break;
    case 'i': /* Berechnen der Tiefe nach Eingabe */
    case 'I': /* der gemessenen Zeit */
    addstr("\n\n\n\t\t Zeit vom Loslassen des Steines bis zum ");
    addstr("\n\t\t Eintreffen des Schalls in Sekunden : ");
    addstr("\n\t\t ");
    getstr(str);
    sscanf(str,"%lf",&zeit);


    tiefe1 = zeit * zeit * ERDBESCHL / 2; /* Berechnung der */
    zeit2 = tiefe1/SCHALL; /* beiden Grenzwerte */
    tiefe2 = (zeit - zeit2) * (zeit - zeit2) /* 'tiefe1' u.'tiefe2'*/
    * ERDBESCHL / 2;


    sprintf(str,"\n\n\t\t Oberer Grenzwert: = %lf Meter" ,tiefe1);
    addstr(str);
    sprintf(str,"\n\t\t Unterer Grenzwert: = %lf Meter\n\n" ,tiefe2);
    addstr(str);
    i = 0;
    do
    {
    i++;
    tiefe = .5 * (tiefe1+tiefe2); /* Mitte zw. tiefe1 u. tiefe2*/
    diff = (2*tiefe/ERDBESCHL) /* Abweichung der berechneten*/
    +tiefe/SCHALL - zeit; /* von der gemessenen Zeit. */


    if (diff >= 0.0) /* Das Intervall wird neu */
    tiefe1 = tiefe; /* festgelegt. */
    else
    tiefe2 = tiefe;


    sprintf(str,"\n\t\t %1d .Berechnungslauf: %5.2f Meter",i,tiefe);
    addstr(str);
    } while (fabs(diff) > ABWEICHUNG);/* solange bis die Zeit nur */
    /* noch um die festgelegte */
    /* Abweichung von der gemessenen entfernt ist */
    wait();
    break;
    case 't': /* Ausgeben einer Tabelle fuer Zeiten */
    case 'T': /* zwischen 1 und 10 Sekunden */
    addstr("\n\n\n\n\t\t Tabelle fuer gemessene Zeiten ");
    addstr("\n\t\t von 1 bis 10 Sekunden:");
    addstr("\n\n\t\t Sekunden Meter");
    for( zeit = 1.0; zeit <= 10.0 ; zeit++)
    {
    x = (double)(zeit/SCHALL + 1/ERDBESCHL);
    y = (double)(zeit/SCHALL);
    tiefe = (double)( SCHALL * SCHALL * ( x -(x * x - y * y )));
    sprintf(str,"\n\t\t %4.1f %5.1f ",zeit,tiefe);
    addstr(str);
    }
    wait();
    break;
    case 'x':
    mvaddstr(23,COL,"Programmende");
    break;


    default: /* Anweisungsblock des */
    mvaddstr(23,COL,"Falscher Kennbuchstabe");/* Fehlerfalles */
    wait();
    break;
    }
    }while(kennbuchst != 'x'); /* Ende der do - while-Schleife */
    endwin();
    }
    /***********************************************************************/
    /* Die Funktion 'wait' gibt einen Text aus und wartet auf 'RETURN' */
    /***********************************************************************/
    void wait(void)
    {
    mvaddstr(24,1,"Bitte die Taste RETURN druecken!");
    while( getch() != RETURN );
    }
    /************************************************************************/



    mfg
    Juno

  • Nunja da musst du halt die Berechnung in der do while schleife durch die rekusive Funktion ersetzen.



    Achso der Konstrukt


    case 't': /* Ausgeben einer Tabelle fuer Zeiten */
    case 'T': /* zwischen 1 und 10 Sekunden */
    // Anweisungen
    break;



    Funktioniert so wie er soll? (auf T und t sensitiv)

  • Ich schreibe einfach , was ich gemacht habe.
    - Nach case ' I' und die Funktion:


    case 'r': /* Berechning der Tiefe nach Eingabe */
    case 'R': /* der gemessenen Zeit durch Rekursion */
    addstr("\n\n\n\t\t Zeit vom Loslassen des Steines bis zum ");
    addstr("\n\t\t Eintreffen des Schalls in Sekunden : ");
    get_string(str);
    sscanf(str,"%lf",&zeit);
    printf("\n");
    tiefe=(0.5*(zeit*zeit*ERDBESCHL));
    zeit=(tiefe/SCHALL+ sqrt(2.0*tiefe/ERDBESCHL));
    x = SCHALL*sqrt(2.0/ERDBESCHL);
    y =SCHALL*zeit;
    i=0;
    schacht_tiefe(0.5*ERDBESCHL*zeit*zeit);

    wait();
    break;
    ***********************************************************************/
    /* Die Funtion 'schacht_tiefe()'- Rekursive Berechnung */
    /**********************************************************************/
    double schacht_tiefe(double rekursion)
    {
    char str[100];
    i++;
    sprintf(str,"\t\t %1d .Berechnungslauf: %5.3lf Meter\n",i,rekursion);
    addstr(str);
    if (fabs(rekursion+x*sqrt(rekursion)-y)>10.e-3)
    rekursion = schacht_tiefe((2.0*y*sqrt(rekursion)-x*rekursion)/(2.0*sqrt(rekursion)+x));
    return(rekursion);
    }
    mfg
    Juno

  • Das sieht doch eher unsauber aus.


    1. Du beziehst dich in der Rekursion auf den Wert von i den du in main Eingeführt hast. in C wird das wahrscheinlich compeliert werden, denn dort ist ja die Variablendefinition auch mitten im Programm möglich und wird nicht wie bei pascal u.ä. in einem extra Definitionsblock gemacht (lokal und global)
    Alerdings ist es wahrscheinlich das dein I=0 dir nichts bringt denn es wird in der rekursion wohl neu generiert und ist unbestimmt. es kann den glücklichen zufall geben das die Speicherbereiche dieselben sind. Aber wahrscheinlicher ist es dass in i nur unsinn steht.


    Naja ob der compiler das macht ist compiler und einstellungs abhängig.


    2. Die berechnung soll nicht im Aufruf stattfinden sondern in der Funktion


    Eine Funktion wie int wait(int tiefe1, int tiefe2, usw) wäre wohl deutliich sauberer. Ansonsten ist die Berechnung ja nicht vollständig in der Funktion.

  • Hi.
    Ich sehe das auch, daß die Funktion nicht sauber ist, aber es funktioniert.
    Wie würdest du die Funktion und Berechnung stellen.


    die Konstanten:
    # define SCHALL 330.0
    #define ERDBESCHL 9.81
    /*************************************/
    double zeit,;
    double tiefe, tiefe1, tiefe2;
    double x, y;


    Gruß
    Juno