Iteration reele Zahlen mit 0,1



  • Hallo 😎

    Welche Probleme bringt eine Iteration über reellen Zahlen mit sich, z.B. das Durchlaufen einer Schleife von -4,3 bis 19,6 in Schritten von 0,1?



  • eigentlich keine. müsstest nur einen float oder double nehmen



  • Dass keine deiner Zahlen als float oder double exakt darstellbar ist. Du wirst also nicht genau bei 19,6 bzw. der Zahl, die dein Rechner für 19,6 hält ankommen.



  • ah danke Bashar.

    Aber kannst du mir das etwas genauer erklären, würde mich freuen 8).



  • MarcR schrieb:

    ah danke Bashar.

    Aber kannst du mir das etwas genauer erklären, würde mich freuen 8).

    0.1 ist im Dualsystem eine periodischer Bruch. Da der Computer nicht unendlich viele Stellen darstellen kann, muss er runden. Also kommt es zu rundungsfehlern beim rechnen mit 0.1.



  • ah danke.



  • Ein beliebtes Umgehen davon ist übrigens, bei Fließkommawerten nicht auf Gleichheit zu testen (a==b), sondern zu prüfen, ob die beiden sich nur winzig bisschen unterscheiden ( abs(a-b) < 0.00001 ).



  • Badestrand schrieb:

    Ein beliebtes Umgehen davon ist übrigens, bei Fließkommawerten nicht auf Gleichheit zu testen (a==b), sondern zu prüfen, ob die beiden sich nur winzig bisschen unterscheiden ( abs(a-b) < 0.00001 ).

    Das Funktioniert aber nur bei kurzen berechnungen mit Zahlen, die alle ungefähr die selbe Größenordnung haben. Bei beliebig großen Zahlen und beliebig langen rechnungen ist der Fehler, der auftritt beliebig groß.



  • Oder aber man arbeitet mit ints und teilt diese, wenn sie benötigt werden, durch 10. So ist zumindest die Iteration an sich kein Problem mehr.



  • Fellhuhn schrieb:

    Oder aber man arbeitet mit ints und teilt diese, wenn sie benötigt werden, durch 10. So ist zumindest die Iteration an sich kein Problem mehr.

    Oder: Wenn man mit gleitkommazahlen Arbeitet, kann man unter umständen auch vorher ausrechnen, wie viele Schritte man benötigt und dann in der Schleife mit einer Integer-Variablen zählen.



  • Die Probleme, die bei der Iteration von Fließkommazahlen auftreten, wurden ja schon erläutert. Die schulmäßige Lösung für dieses Rundungsproblem sieht so aus, dass immer eine Integer-Variable inkrementiert wird und die gewünschte Fließkommazahl jedesmal neu berechnet wird, um die Akkumulation der Rundungsfehler zu vermeiden.

    double von = -4.3;
        double bis = 19.6;
        double step = 0.1;
        double x;
        for( int iStep = 0; (x = von + iStep * step) <= bis; ++iStep )
        {
            // mache was mit x
        }
    

    man kann sich hier auch nicht darauf verlassen, dass x als letzen Wert den Wert 19.6 erreicht - bei diesem Zahlenbeispiel ist es nicht so. Das liegt daran, dass der interne Wert von 19.5 (kann noch exakt dargestellt werden) + 0.1 eben nicht identisch 19.6 ist. Hier schlägt bereits der Rundungsfehler zu.

    Wenn man sicher ist, dass es sich bei [von, bis] um ein geschlossenes Intervall handelt und der letze Wert (bis = 19.6) noch sicher erreicht werden soll, so sollte man die obere Grenze um step/2 nach oben schieben - also

    for( int iStep = 0; (x = von + iStep * step) < (bis + step/2); ++iStep )
    

    Gruß
    Werner


Anmelden zum Antworten