Ankündigung

Einklappen
Keine Ankündigung bisher.

Genauigkeit der Berechnung

Einklappen

Neue Werbung 2019

Einklappen
Dieses Thema ist geschlossen.
X
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Genauigkeit der Berechnung

    Hallo.

    Ich habe jetzt erst angefangen PHP zu lernen und bin auf ein Problem gestoßen, bei dem ich nicht weiß, wie man es lösen kann.

    Wenn man in einer Subtraktion z.B. 10.01 - 10 eingibt, kommt nicht wie erwartet 0.01 heraus sondern 0.0099999999999998.

    Dach ich aber das Ergebnis weiterverarbeiten muss, sind die nachfolgenden Berechnungen aber auch ungenau.

    Was muss man machen, damit man im Beispiel 0.01 als Ergebnis bekommt.
    Ich gehe nicht davon aus, dass man den zusätzlichen Schritt über eine Round verwenden muss, da die Anzahl der Nachkommastellen immer
    Unterschiedlich ist.

    Schon Jetzt Danke für die Unterstützung.

    Gruß,
    Stefan

  • #2
    Entweder runden oder mit den BCMath-Funktionen rechnen, denn diese arbeiten mit String- statt mit Float-Werten.

    Kommentar


    • #3
      Zitat von StefanHue Beitrag anzeigen
      Hallo.

      Ich habe jetzt erst angefangen PHP zu lernen und bin auf ein Problem gestoßen, bei dem ich nicht weiß, wie man es lösen kann.

      Wenn man in einer Subtraktion z.B. 10.01 - 10 eingibt, kommt nicht wie erwartet 0.01 heraus sondern 0.0099999999999998.

      Dach ich aber das Ergebnis weiterverarbeiten muss, sind die nachfolgenden Berechnungen aber auch ungenau.

      Was muss man machen, damit man im Beispiel 0.01 als Ergebnis bekommt.
      Ich gehe nicht davon aus, dass man den zusätzlichen Schritt über eine Round verwenden muss, da die Anzahl der Nachkommastellen immer
      Unterschiedlich ist.

      Schon Jetzt Danke für die Unterstützung.

      Gruß,
      Stefan
      Du willst 0.01 herausbekommen? Wirklich? Oder 0.0100000000000000? Reg' dich jetzt bitte nicht auf, aber das ist der springende Punkt.

      Willst du wirklich ein auf die 16. Nachkommastelle genaues Ergebnis? Willst du einen Laserstrahl zum Mond schicken oder was soll das werden?

      Ich weiß, es wird dir nicht gefallen, aber dein Problem ist mitnichten ein EDV-Problem. Es ist ein Problem mit dem Rechnen und mit dem Umgang mit Zahlen.

      Jetzt die Lösung, sozusagen die "Musterlösung":
      1. Ungenauigkeiten in der 14. - 16. Stelle nach dem Komma sind bei Computer-Berechnungen unvermeidlich, weil der Rechner intern alle Berechnungen außer Addition/Subtraktion auf logarithmischer Basis berechnet.
      2. Trotzdem ist die Berechnung auf der Grundlage von Float-Zahlen die mit den meisten Vorteilen.
      3. Problematisch ist immer eine Kombination aus Addition/Subtraktion auf der einen und Multiplikation/Division bzw. Potenzieren/Wurzelziehen/Logarithmieren auf der anderen Seite. Da beim Multiplizieren/Dividieren/Potenzieren usw. immer nur die gleiche Anzahl signifikanter Stellen herauskommt, bleibt einem im Endeffekt nichts übrig, als jegliches Endergebnis auf die kleinste Anzahl an Nachkommastellen, die in Zwischenergebnissen auftauchen, zu runden (außer, es sind eh feste Regeln vorgegeben, wie im Steuerrecht bzw. Rechnungswesen allg.).
      4. Der Pkt. 3. gilt unabhängig davon, ob der Rechner/die Software mit Float-Zahlen oder Decimal rechnet. Decimal-Zahlen sind bei kaufmännischen Berechnungen vorzuziehen, bei wissenschaftlichen Berechnungen liefern sie allenfalls Scheingenauigkeiten.
      5. Auf der Grundlage von 1. - 4. hat es sich bewährt, sämtliche Zwischenergebnisse mit 4 Nachkommastellen zu berechnen und das Ergebnis auf 2 Nachkommastellen zu runden.
      Halte dich daran und dein Problem ist verschwunden.

      Bemerkung: Da du hier offenbar auf anspruchsvoller Basis mit Zahlen hantieren willst, solltest du über entsprechende Grundlagen verfügen. Das ist bei dir ganz offensichtlich nicht der Fall.

      P.S. Mir fällt da noch eine Frage ein, die ich dir gerne stelle, weil dir dann vielleicht ein Licht aufgeht:
      Du schreibst ja u.a.
      Dach ich aber das Ergebnis weiterverarbeiten muss, sind die nachfolgenden Berechnungen aber auch ungenau.
      Meine Frage: Wie ungenau sind die denn dann?

      Kommentar


      • #4
        Die Lösung hat hellbringer doch schon genannt.

        PHP-Code:
        var_dump( (float)bcsub(10.01102) );
        var_dumpround(10.01 102) ); 
        Links zum Nachlesen:
        bcsub
        floats im Handbuch erklärt

        Kommentar


        • #5
          Zitat von protestix Beitrag anzeigen
          Die Lösung hat hellbringer doch schon genannt.

          PHP-Code:
          var_dump( (float)bcsub(10.01102) );
          var_dumpround(10.01 102) ); 
          Links zum Nachlesen:
          bcsub
          floats im Handbuch erklärt
          Nochmal: Die Lösung liegt hier nicht im Verständnis von float, round etc. Wer sagt dir denn z.B., protestix, daß 2 Nachkomma-Stellen für die Berechnung, die der TE ausführen will, ausreichend sind. Versuche mal, die Probleme nicht von der technischen, sondern auch von der fachlichen Seite aus zu beurteilen. Wir hatten das Problem bereits bei dem Thread, dem ein simpler Fehler in der Struktur der DB zugrundelag, dann aber von einigen "Größen" zu einer Grundsatzdiskussion über das Runden im Zusammenhang mit der MWSt "umgelenkt" wurde. Da hattest du einen viel besseren Vorschlag zur Hand, den ich gerne zitiere:
          Wenn man in der DB aber immer 2 Stellen mehr nimmt als die kleinste Untereinheit einer Währung, wird zumindest der Fehler minimiert.
          Das liefe hier, da der TE ganz deutlich davon sprach, daß das obige ein Zwischenergebnis ist, auf das bewährte Schema 4/2 (4 für Zwischenerg., 2 für Endergebnis) hinaus.

          Ich sage ja nicht, daß jetzt auf einmal alle ITler Mathe-Spezialisten werden müssen. Aber hier geht es im Endeffekt nur um "gesunden Menschenverstand" und ein "gutes Verhältnis zur Welt der Zahlen". Wer das nicht hat - ob "Frager" oder "Berater" - sollte da ein wenig aufholen oder entsprechend zurückhaltend sein - IMHO (selbstverständlich, was denn sonst?!... ).

          Kommentar


          • #6
            Zitat von StefanHue Beitrag anzeigen
            Was muss man machen, damit man im Beispiel 0.01 als Ergebnis bekommt.
            Antwort in Beitrag #2.

            Wer sagt dir denn z.B., protestix, daß 2 Nachkomma-Stellen für die Berechnung, die der TE ausführen will, ausreichend sind.
            10.01 - 10 = 0.01
            Es werden auch nicht mehr Nachkommastellen nur weil ich mehr anfordere.

            PHP-Code:
            // Unterschied round zu bcmath
            $digits =0;
            while( 
            $digits 18 ){
                echo 
            "{$digits} Nachkommastellen: ""<br>\n";
                
            var_dump( (float)bcsub(10.0110$digits) ); 
                
            var_dumpround(10.01 10$digits) );  
                
            $digits $digits 1;  

            ab 15 Nachkommastellen gibt round auf.

            Wenn man mehr Stellen braucht, weil Minuend und Subtrahend unbekannt sind, ist das in Ordnung wenn man mehr Nachkommastellen zur Verfügung stellt. Das muss man sich jedoch vorher überlegen.

            Trotzdem ist die Berechnung auf der Grundlage von Float-Zahlen die mit den meisten Vorteilen.
            Unsinn, sieht man doch hier, dass es unvorteilhaft ist.

            Das Thema hatten wir hier schon öfter detailliert diskutiert und muss nicht immer und immer wieder durchgekaut werden.
            BCmath verwenden und die Probleme sind aus der Welt.






            Kommentar


            • #7
              Zitat von protestix Beitrag anzeigen
              10.01 - 10 = 0.01
              Es werden auch nicht mehr Nachkommastellen nur weil ich mehr anfordere.
              ...
              ab 15 Nachkommastellen gibt round auf.

              Wenn man mehr Stellen braucht, weil Minuend und Subtrahend unbekannt sind, ist das in Ordnung wenn man mehr Nachkommastellen zur Verfügung stellt....
              BCmath verwenden und die Probleme sind aus der Welt.
              Merkst du was?

              Ich würde sagen: "BCmath verwenden und die Probleme scheinen durch Scheingenauigkeit aus der Welt zu sein."

              Du hast, genau wie der TE, das Thema Rundung und Genauigkeit nicht verstanden. Das mußt du aber auch nicht, dafür gibt es Mathematiker, Ingenieure, Betriebswirte, Kaufleute usw., die fachlich Bescheid wissen. Dein Fehler ist nicht, daß du die Frage falsch beantwortest, sondern dein Vorgehen als IT-Experte. IT kann nicht, wie du meinst (oder aus geschäftlichen Gründen vorgibst), alle Fragen beantworten. Sie muß sich stets mit der Fachdisziplin, für die sie Anwendungen bereitstellt, konsultieren.

              Was heißt das konkret? Nun, das erste ist, daß man Rückfragen stellt. Du schreibst:
              Wenn man mehr Stellen braucht, weil Minuend und Subtrahend unbekannt sind, ist das in Ordnung wenn man mehr Nachkommastellen zur Verfügung stellt. Das muss man sich jedoch vorher überlegen.
              Die Zahl der Stellen - also die Genauigkeit - die man "braucht" hängt nicht von Bekanntheit oder Unbekanntheit der Variablen bzw. beteiligten Rechengrößen ab. Zunächst einmal ist sie auch nicht "benötigt" (im Sinne von "brauchen"), sondern allenfalls "gewünscht". Ob sie überhaupt realisierbar ist, hängt von den Rechengrößen ab, die verwendet werden. Die müssen, was den Betrag betrifft, nicht bekannt sein, aber ihre Genauigkeit muß bekannt sein. Das ist in 99% aller Fälle möglich, also ist das deine 2. Frage als ITler an den Auftraggeber: Mit welcher Genauigkeit liegen die Ausgangsgrößen vor?

              Was den TE betrifft, lautet diese Frage: Ist in der Aufgabe 10.01 oder 10.0100000000000000 gemeint. Wenn nun die Genauigkeit bei beiden beteiligten Größen 16 Nachkommestellen beträgt, hat der TE "das Recht", auch im Ergebnis die 16 Nachkommastellen zu "fordern". Dann und nur dann gilt, was du schreibst:
              ab 15 Nachkommastellen gibt round auf.
              Das ist aber auch kein Problem, denn er braucht diese Genauigkeit gewöhnlich nicht - außer wenn er einen Laserstrahl zum Mond schicken möchte.

              Es folgen weitere Rückfragen, die wir hier nicht stellen können, weil der TE sich zu den bereits gestellten überhaupt noch nicht geäußert hat.

              Ein weiteres Problem, das du überhaupt noch nicht berücksichtigt hast, ist der Unterschied zwischen der Fehlerfortpflanzung bei der Addition/Substraktion im Vergleich zur Multiplikation usw. ist, daß sich bei letzterer die Zahl der signifikanten Stellen "fortpflanzt". Einfaches Beispiel: x = 1 / 7 Ergebnis lt. Taschenrechner auf meinem Smartphone: 0.1428571429 Aber stimmt das? Natürlich nicht, das Ergebnis ist, wenn als Zähler 1.000 gegeben ist, z.B. 0.1429, wobei die letzte Stelle zweifelhaft ist und weggerundet werden sollte: x = 0.143!

              Hier trifft also zu, was du schreibst:
              Das muss man sich jedoch vorher überlegen.
              Ist man dazu wie der TE oder Du nicht in der Lage, weil Grundlagen fehlen, muß man sich entsprechenden Beistand suchen. Es ist nicht unehrenhaft und stellt auch deine Kompetenz als ITler nicht in Frage, wenn du dies "zuläßt".

              Zum Vergleich float vs BCmath schreibst du:
              Unsinn, sieht man doch hier, dass es [=float] unvorteilhaft ist.
              Mal abgesehen davon, daß du weit davon entfernt bist, in diesen Fragen und was meine Aussagen betrifft, über "Sinn und Unsinn" zu befinden: Es ist ein Vergleich zwischen Lügner und Scharlatan. Außer für den in der Realität möglichen Fall, daß man einen Laserstrahl zum Mond schicken will (und wer das tut, hat das Thema verstanden!) ist es vollkommen unerheblich, ob ich float oder BCmath verwende: Entweder erlauben meine Ausgangsgrößen eine hohe Zahl an Nachkommastellen oder nicht. Im letzteren Fall ist die Verwendung von BCmath dann allenfalls "Lügen auf hohem Niveau"!
              Das Thema hatten wir hier schon öfter detailliert diskutiert und muss nicht immer und immer wieder durchgekaut werden.
              Es wird immer wieder auftauchen und durchgekaut werden, weil solche Dinge in der Regel falsch verstanden werden. Allerdings: Man kann unnötige Diskussionen vermeiden, wenn man sich vorher ein wenig schlau macht. Wenn das aus welchen Gründen auch immer (kann ja auch passieren, daß jemand sich "schlau machen" will, das aber nicht funktioniert... ) nicht geht, einfach mal den Nuhr beachten...






              Kommentar


              • #8
                StefanHue
                Wahrscheinlich denkst du, daß das obige eine "Experten-Diskussion" ist, die dich nicht betrifft. Tatsächlich betrifft sie dich, aber frag nicht wie...

                Konkret:
                1. Mit welcher Genauigkeit (Nachkommastellen, signifikante Stellen) liegen deine Ausgangsdaten vor?
                2. Welche Genauigkeit ist im Ergebnis erforderlich?
                3. In welchem fachlichen Kontext steht deine Aufgabe?

                Kommentar


                • #9
                  nicht geht, einfach mal den Nuhr beachten..
                  Was für ein Nuhr, kenne ich im Zusammenhang mit Zahlen nicht.

                  Davon abgesehen bin ich hier raus, da ich eh nicht in der Lage bin 2 Zahlen zu subtrahieren.

                  Kommentar


                  • #10
                    http://weitz.de/ieee/

                    ...10.01 - 10 eingibt, kommt nicht wie erwartet 0.01...
                    Diese Erwartungshaltung hatte ich auch, seinerzeit als wir noch mit der Kreide an der Tafel standen....

                    Kommentar


                    • #11
                      Was den TE betrifft, lautet diese Frage: Ist in der Aufgabe 10.01 oder 10.0100000000000000 gemeint.
                      Warum denn da stoppen?
                      Vielleicht braucht der TE ja eher 10.01000000000000000000000000000000000000000000000 00000

                      Nur, irgendwann wird es halt lächerlich.
                      [COLOR=#A9A9A9]Relax, you're doing fine.[/COLOR]
                      [URL="http://php.net/"]RTFM[/URL] | [URL="http://php-de.github.io/"]php.de Wissenssammlung[/URL] | [URL="http://use-the-index-luke.com/de"]Datenbankindizes[/URL] | [URL="https://www.php.de/forum/webentwicklung/datenbanken/111631-bild-aus-datenbank-auslesen?p=1209079#post1209079"]Dateien in der DB?[/URL]

                      Kommentar


                      • #12
                        Das liegt am System der Gleitkommazahlen.
                        Hier findest du ein Beispiel : https://detlefhahn.de/c_programmieru...ma_ungenau.php
                        0,4 z.B. ist keine Potenz von 2 und deshalb nicht exakt darstellbar.
                        Lass dich nicht verrückt machen. Die wenigsten Leute wissen den Zusammenhang und berrechnen munter mit Execl und Co.
                        Wem fallen schon Rundungsdifferenzen auf, ausser evtl einem genauen Buchhalter.
                        Nur wenn dann evtl ein unbedarfter Programmierer zwei Float auf = vegleicht, fällt dann evtl mal eine Maschine vom Himmel oder
                        etwas anders crasht (ein bischen Schwund muß sein)..

                        Ich findes es jedenfalls gut, das du dir Gedanken machst und fragst.

                        Kommentar


                        • #13
                          Abgesehen davon, dass php schon der datentypen wegen wohl nicht die optimale sprache für komplexe berechnuingen ist, ist in #2 alles gesagt.

                          Kommentar


                          • #14
                            Zitat von tomBuilder Beitrag anzeigen
                            Abgesehen davon, dass php schon der datentypen wegen wohl nicht die optimale sprache für komplexe berechnuingen ist, ist in #2 alles gesagt.
                            ... noch einer.

                            Kommentar


                            • #15
                              Wenn man in einer Subtraktion z.B. 10.01 - 10 eingibt, kommt nicht wie erwartet 0.01 heraus sondern 0.0099999999999998.

                              Was muss man machen, damit man im Beispiel 0.01 als Ergebnis bekommt.
                              Zitat von protestix Beitrag anzeigen
                              Die Lösung hat hellbringer doch schon genannt.
                              ...
                              Links zum Nachlesen:
                              bcsub
                              floats im Handbuch erklärt
                              Und auf das Handbuch wurde auch schon verwiesen. Große rote Box! -> https://www.php.net/manual/de/langua...ge.types.float
                              Dort steht eigenlich eh auch alles.
                              The string "()()" is not palindrom but the String "())(" is.

                              Debugging: Finde DEINE Fehler selbst! | Gegen Probleme beim E-Mail-Versand | Sicheres Passwort-Hashing | Includes niemals ohne __DIR__
                              PHP.de Wissenssammlung | Kein Support per PN

                              Kommentar

                              Lädt...
                              X