Sinus in while-Schleife



  • Hallo!

    Ich hatte in der Schule C++Programmieren und jetzt muss ich mich für die Uni nach Jahren wieder damit herumschlagen:)
    Bis jetzt funktioniert alles ganz gut und hab sogar Spaß dran. Bis auf ein kleines Detail mitdem ich mich jetzt schon ewig herumschlage:

    Arbeitsaufgabe ist:
    "Schreiben Sie ein Programm das die Funktionswerte des Sinus an den Punkten x element von [0,1] berechnet. Die Punkte sollen den Abstand Deltax haben welcher vom Programm als freier Parameter eingelesen wird. Das Programm muss einen while-Loop enthalten. Die Sinusfunktion wird in C++ mit sin(x); aufgerufen"

    Problem
    Hier in dem Programm, wenn ich "Delta-x" als 0.1 wähle, funktioniert alles perfekt.
    Wenn ich jedoch "Delta-x" als 0.01 oder 0.001 wähle wird der letzte Wert(also der Wert 1) nicht ausgegeben!

    Das Programm:

    #include <iostream>
    #include <math.h>
    #include <cmath> //NEBENFRAGE: Was is der Untershcied zwischen <math.h> und <cmath>?
    using namespace std;
    
    int main()
    {
    double deltax, rechenvar;
    rechenvar=0;
    
    cout << "Gib ein Delta-x ein!";    
    cin >> deltax;
    
    while ( rechenvar <=1 )
           {               
            cout << "Sinus von " << rechenvar << ":" << sin(rechenvar) << endl;
            rechenvar=rechenvar+deltax;  
    
           }   
    
    return 0;    
    }
    


  • Hoffe einer von euch kann mir helfen, ich glaube nicht dass ich einen Fehler übersehen habe, sondern einfach dass ich den Fehler nicht "verstehe":)



  • müsste an rundungsfehlern bei der binärdarstellung der dezimalzahlen sein. Hab mir das eben im debugger angeschaut und im schritt in dem eigentlich 1.0 erscheinen müsste, hat die variable tatsächlich den wert 1.00000000000007(so ca.).
    Das hat sich aber schon vorher eingeschlichen.


  • Mod

    Ja, das sind die Rundungsfehler.

    Zu der Zusatzfrage: cmath ist die C++-Version des C-Headers math.h. Wie auch alle anderen C-Header ihr äquivalent haben: stdio.h ist cstdio, stdlib.h ist cstdlib, usw. In den C++ Headern sind die Funktionen im Namensraum std (in der Praxis aber trotzdem auch noch im globalen Namensraum 😞 ) und bis vor kurzem waren die Header standardmäßig auf dem Stand von C89 (in der Praxis auf dem Stand des C-Comopilers des Systems) seit C++11 ist vieles auf den Stand von C99 gebracht, insbesondere die cmath.

    Und bei so einer Aufgabe würde ich schon aus Prinzip irgendwo einfach nur while(0) {} hin schreiben und den Rest so machen wie ich es für richtig halte.



  • SeppJ schrieb:

    Und bei so einer Aufgabe würde ich schon aus Prinzip irgendwo einfach nur while(0) {} hin schreiben und den Rest so machen wie ich es für richtig halte.

    +1
    Ich würde allerdings noch eine kompliziertere Schreibweise für 0 verwenden. Irgendwas mit Bitoperationen oder so.

    Edit: Oder sowas:

    // Code für Sinus
    
    while(new (std::nothrow) int);
    


  • NeverMind1959 schrieb:

    Problem
    Hier in dem Programm, wenn ich "Delta-x" als 0.1 wähle, funktioniert alles perfekt. Wenn ich jedoch "Delta-x" als 0.01 oder 0.001 wähle wird der letzte Wert(also der Wert 1) nicht ausgegeben!

    Dein Computer rechnet intern nicht mit Dezimalzahlen sondern (wahrscheinlich) mit Binärzahlen. Damit sind Zahlen wie 0.1, 0.01, 0.001 mit endlicher Anzahl von Stellen nicht exakt darstellbar. Das ist so ähnlich wie 1/3 im Dezimalsystem. 1/3 = 0,333333333.... Im Zwölfersystem ist 1/3 aber mit endlich vielen Stellen darstellbar: 1/3 = 0,412. Die erste Stelle hinter dem Komma ist nämlich dort die Stelle für Zwölftel und vier Zwölftel sind ein Drittel. Eine Fließkommazahl speichert nun eine endliche Zahl von Stellen (damit das noch in endlich viele Bits reinpasst). Die Periode wird also irgendwo abgebrochen bzw die Zahl wird gerundet. Die Rundungsfehler pflanzen sich fort und es kommen neue dazu beim Weiterrechnen.


Log in to reply