Announcement

Collapse
No announcement yet.

Float/Double vs. Decimal

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Float/Double vs. Decimal

    Hallo zusammen,

    ich habe heute eine Abfrage versucht und war etwas erschrocken, was da auf mich zugekommen ist.

    Folgendes ist passiert:

    Ein Datenbankfeld mit dem Typ Float ist in der Datenbank, in welchem Preise stehen. (Bsp: 9.99) Ich habe versucht folgenden SELECT abzusetzen.
    Code:
    SELECT * FROM beispiel WHERE preis = '9.99'
    Es hat NICHT funktioniert.

    Folgendes jedoch hat funktioniert:
    Code:
    SELECT * FROM beispiel WHERE preis LIKE '9.99'
    Nach näherem hinschauen stand folgender Wert in der Datenbank:

    9.989999771118164

    Folgendes habe ich in der DOkumentation gefunden:

    "Die Datentypen FLOAT und DOUBLE werden zur Darstellung annähernder numerischer Datenwerte verwendet. Für FLOAT gestattet der SQL-Standard optional die Angabe der Genauigkeit (nicht aber des Bereichs des Exponenten) in Bits, die dem Schlüsselwort FLOAT in Klammern folgen."

    Warum sollte ich also ein Float verwenden??? Was bringt einem diese Ungenauigkeit?

    Ich bin verwirrt :/
    Gruß
    Iloivar

  • #2
    Float oder Double bringen maximale Präzision in Bezug auf die Speichergröße des Feldes. Sie bringen am meisten im wissenschaftlichen Bereich.
    Für Preise nimmt man sie nicht so gerne, das wäre dann decimal.
    Gruß, defo

    Comment


    • #3
      Warum sollte ich also ein Float verwenden??? Was bringt einem diese Ungenauigkeit?
      Es geht nicht um die Ungenauigkeit die bekommt man nur inherent auf Grund des Darstellungsverfahrens mit. Float benutzt man wenn es um die signifikanten Stellen geht irgendwo im Zahlenbereich.

      Versuch mal 0,000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000 0000000012345 und
      12345000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000 00000000000,0
      mit Decimal darzustellen. Fließkommazahlen können das aber eben nur ungefähr.

      Bei Preisen wird man selten das Problem haben drum ist dort Decimal das Richtige (in manchen Sprachen heißt der decimal Datentyp sogar money).

      Comment


      • #4
        Hallo,
        Originally posted by Iloivar View Post
        Ein Datenbankfeld mit dem Typ Float ist in der Datenbank, in welchem Preise stehen. (Bsp: 9.99) Ich habe versucht folgenden SELECT abzusetzen.
        Code:
        SELECT * FROM beispiel WHERE preis = '9.99'
        Es hat NICHT funktioniert.
        Warum fragst du auch ein numerisches Datenfeld mithilfe eines Strings ab? Hier führt der Server eine implizite Typkonvertierung durch und zwar von Float nach String und vergleicht dann die Strings!. Das du da bei Fließkommazahlen nur in den seltensten Fällen eine Übereinstimmung bekommst, liegt ja wohl auf der Hand. Die typgerechte Abfrage sollte dagegen auch die erwarteten Ergebnisse bringen. Hast du also mal:
        [highlight=sql]
        SELECT * FROM beispiel WHERE preis = 9.99
        [/highlight]
        probiert?

        Gruß Falk
        Wenn du denkst du hast alle Bugs gefunden, dann ist das ein Bug in deiner Denksoftware.

        Quellcode ohne ein Mindestmaß an Formatierung sehe ich mir nicht an! Ich leiste keinen Privatsupport per Mail oder PN!

        Comment


        • #5
          Originally posted by Iloivar View Post
          Warum sollte ich also ein Float verwenden??? Was bringt einem diese Ungenauigkeit?

          Ich bin verwirrt :/
          [klugscheissen]
          Das ist Mathematik! Bei Festkommazahlen, also Zahlen mit einer festen Anzahl an Nachkommastellen (ein Teil davon sind die Ganzzahlen, mit 0 Nachkommastellen) hast du abzählbar unendlich viele Zahlen. Die Unendlichkeit entsteht nur dadurch, dass der Bereich nach oben und unten offen ist. Sind diese Grenzen festgelegt, dann gibt es innerhalb dieser auch nur eine exakte, also abzählbare, Anzahl von Zahlen. Im Bereich von 0 -1 hast du bei null Nachkommastellen genau zwei Werte, bei einer Nachkommastelle 11, bei zwei 101 usw.
          Der Bereich der Flieskommazahlen umfasst analog zu den reelen Zahlen einen NICHT abzählbar unendlichen Bereich, da es eben schon zwischen 0 und 1 unendlich viele mögliche Werte gibt. Da man mit einer endlichen Anzahl an Speicherbits eben nicht eine unendliche Anzahl an Werten darstellen kann, kommt es zu den erlebten "Ungenauigkeiten"
          [/klugscheissen]

          Anm.: Ja ich weiß das die "Ungenauigkeiten" auch durch die Art und Weise der Speicherung von Fließkommazahlen in digitaler Form bedingt sind, aber so ist es mglws. anschaulicher.
          Wenn du denkst du hast alle Bugs gefunden, dann ist das ein Bug in deiner Denksoftware.

          Quellcode ohne ein Mindestmaß an Formatierung sehe ich mir nicht an! Ich leiste keinen Privatsupport per Mail oder PN!

          Comment


          • #6
            Danke für eure Antworten. Ist mir nun klarer geworden :-)

            @Falk

            Die 9.99 sind als Float in der DB gespeichert.

            Code:
             SELECT * FROM beispiel WHERE preis LIKE '9.99'
            Funktioniert.

            Code:
             SELECT * FROM beispiel WHERE preis = 9.99
            Funktioniert NICHT.

            Ich saß seeee[...]eehr lange vor dem zweiten Select und bin fast verzweifelt... ;-) Deswegen dieser Thread hier.
            Gruß
            Iloivar

            Comment


            • #7
              Hallo,
              Originally posted by Iloivar View Post
              Code:
               SELECT * FROM beispiel WHERE preis = 9.99
              Funktioniert NICHT.
              Hmmm... hab das jetzt mal versucht nachzuvollziehen und der Eindruck verstärkt sich, dass man lieber die Finger von FLOAT & Co. lassen sollte, wenn man es nicht wirklich braucht und die Konsequenzen in Kauf nimmt. Gerade für einfach nur Preise wäre hier also ein Festkommatyp seehr viel einfacher zu handhaben. Wenn sich an der Struktur nichts mehr ändern lässt, dann würde ich aber trotzdem auf explizite Konvertierung setzen, statt das über String-Vergleiche abzuwickeln.
              Da MySQL offensichtlich einen Wert im SQL nicht zu einem Float-Typ casten kann, bleibt nur der umgedrehte Weg:
              [highlight=sql]
              CREATE TABLE test (
              id int(6) NOT NULL AUTO_INCREMENT,
              preis float NOT NULL,
              PRIMARY KEY (`id`)
              ) ENGINE=MyISAM;

              INSERT INTO test (preis)
              VALUES (9.99);

              SELECT id, CAST(preis AS DECIMAL(16,4)) preis
              FROM test
              WHERE CAST(preis AS DECIMAL(16,4)) = CAST(9.99 AS DECIMAL(16,4));
              [/highlight]

              Gruß Falk
              Wenn du denkst du hast alle Bugs gefunden, dann ist das ein Bug in deiner Denksoftware.

              Quellcode ohne ein Mindestmaß an Formatierung sehe ich mir nicht an! Ich leiste keinen Privatsupport per Mail oder PN!

              Comment

              Working...
              X