Sebastian Jurk: BCMath fehlerhaft?

Hallo,

da habe ich jetzt mein PHP-Projekt auf BCMath umgestellt, überall wo es um float-Zahlen geht, um möglichst hohe Genauigkeit zu erhalten und jetzt rechnet das falsch...

Beispiel: ~~~php bcscale(8);
echo bcadd(9.88000000, 0.00005).' - '.bcadd(9.88000000, 0.0005);

  
Ergebnis: 9.88000000 - 9.88050000  
  
Das Verändern von bcscale ändert auch nichts.  
  
Ist ein normaler Bug oder?  
  
\*seufz\* Und ich dachte diese Funktionen sind extra für genaues rechnen gemacht. Ich frage mich wie viele Webseiten deswegen falsch rechnen und dabei mit Geld hantieren.  
  
Grüße!  
Sebastian
  1. Scheinbar passiert das selbe mit den Funktionen bcadd, bcsub, bcdiv und bcmul. Die 5.Stelle nach dem Komma wird wohl nicht beachtet und deswegen wird die ganze Zahl als 0 gewertet.

    Soll ich dazu mal einen Bug im php bugtracker erstellen oder gibts irgendwie eine gute Erklärung dafür?

    1. Moin!

      Scheinbar passiert das selbe mit den Funktionen bcadd, bcsub, bcdiv und bcmul. Die 5.Stelle nach dem Komma wird wohl nicht beachtet und deswegen wird die ganze Zahl als 0 gewertet.

      Soll ich dazu mal einen Bug im php bugtracker erstellen oder gibts irgendwie eine gute Erklärung dafür?

      Ja, die gibts: Du verwendest float-Zahlen, die du als Parameter an bcmath übergibst. Für diese Zahlen gelten dieselben Einschränkungen hinsichtlich Genauigkeit und Rundungsfehlern.

      Die einzige Möglichkeit, beliebig genaue Zahlen in PHP zu behandeln, ist als STRING. Deshalb erlauben die bcmath-Funktionen auch nur Strings als Parameter, und PHP wandelt Zahlen still und leise in Strings um.

      - Sven Rautenberg

      1. Ok, danke... dass Strings Zwang und nicht nur Feature sind hatte ich nicht erkannt. Jetzt funktioniert es.

        Danke!
        Sebastian

  2. [latex]Mae  govannen![/latex]

    Beispiel: ~~~php

    bcscale(8);

    echo bcadd(9.88000000, 0.00005).' - '.bcadd(9.88000000, 0.0005);

    
    >   
    > Ergebnis: 9.88000000 - 9.88050000  
      
    Ergebnis: 9.88005000 - 9.88050000  
      
    Lies nochmal in der Doku unter Parameters, was \*genau\* bcxxxx() erwartet  
      
    Stur lächeln und winken, Männer!  
    Kai
    
    -- 
    It all began when I went on a tour, hoping to find some furniture  
     Followed a sign saying "Beautiful Chest", led to a lady who showed me her best)  
    [SelfHTML-Forum-Stylesheet](http://selfhtml.knrs.de/#h_stylesheet)
    
    1. Ok, danke... dass Strings Zwang und nicht nur Feature sind hatte ich nicht erkannt. Jetzt funktioniert es.

      Danke!
      Sebastian

      1. Tach!

        Ok, danke... dass Strings Zwang und nicht nur Feature sind hatte ich nicht erkannt. Jetzt funktioniert es.

        Dann solltest verinnerlichen, dass das Problem der Datentyp Float ist, der aufgrund der verwendeten Binärtechnik nicht in der Lage ist, exakte gebrochene Zahlen abzubilden. Du musst den Float-Typ komplett außen vor lassen - ohne Ausnahme, inklusive der Funktionen, die Float liefern oder verarbeiten.

        dedlfix.

        1. Dazu gehören dann natürlich auch ursprüngliche Init-float-werte für Variablen. Gut dass du das erwähnst weil im Hinterkopf hatte ich immer noch dass die Probleme erst entstehen wenn das Rechnen beginnt.

          Ist aber schon etwas schräg dass man strings braucht um genau rechnen zu können.

          Grüße!
          Sebastian

          1. Hallo Sebastian,

            Ist aber schon etwas schräg dass man strings braucht um genau rechnen zu

            nun, bei Strings kannst du Zahlen mit fast beliebig vielen Stellen angeben, aber sobald du etwas als Zahl darstellst, unterliegt es den Genauigkeiten der Kodierung. Bei doppelt genauen Fließkommazahlen ist das 10^-15. Uns Naturwissenschaftler hat das bisher nicht gestört, da wir doch nicht so genau messen können. Die Bänker wird es auch erst stören, wenn auf einem Konto mehr als 10^15 Cent liegen. :)

            Gruß, Jürgen

            PS Mit welchem Problem beschäftigst du dich eigentlich, wenn du so genau rechnen musst?

            1. Ein Tradingbot... :) Die Preise sind bis auf 8 Stellen nach dem Komma genau. Und es ist mir dann zumindest aufgefallen dass das alles nicht richtig rechnet.

              Immerhin, habe ich jetzt mal ein wenig getestet, klappt es gut mit Stringzahlen zu arbeiten. Auch Vergleiche, größer, kleiner als usw funktionieren. Sonst hätte man da auch wieder umwandeln müssen. Oder if($var) wenn diese eine Zahl '0' oder etwas anderes enthält funktioniert. Also offenbar kann man Floatzahlen komplett als String handlen ohne in float zurückwandeln zu müssen. Das ist schon mal gut.

              Grüße!
              Sebastian

              1. Hallo Sebastian,

                ... Die Preise sind bis auf 8 Stellen nach dem Komma genau. ...

                das wären dann 1 µCent oder 10 n€. Gibt es einen Grund für diese hohen Genauigkeitsanforderungen?

                Gruß, Jürgen

                1. Ja... die Währung hat weltweit nur 21Millionen Einheiten... wenn sie mal fertig ist. Das heißt wenn mehr Bedarf besteht muss der Wert der einzelnen Coin steigen und die Nachkommastellen könnten erweitert werden um kleinere Beträge weiterhin zu ermöglichen. Um Bitcoins gehts um genau zu sein.

                  Die sind von vorn herein mit 8 Nachkommastellen erschaffen. Können aber problemlos erweitert werden wenn der Bedarf da ist.