MySQL: Spaß mit float

Man nehme folgenden Code:

DROP DATABASE IF EXISTS test;
CREATE DATABASE test;
USE test;
DROP TABLE IF EXISTS test;
CREATE TABLE test (number_double DOUBLE, number_float FLOAT);
INSERT INTO test VALUES (1000000000000000, 1000000000000000);
SELECT number_double, number_float FROM test;
Exponentendarstellung

Exponentendarstellung

Okay, soweit noch keine Sensation. Wenn man nun aber MySQL dazu zwingt, den konkreten und exponentenfreien Wert rauszurücken, indem man folgendermaßen selektiert:

SELECT number_double * 1, number_float * 1 FROM test;

offenbart sich:

Exakter Wert

Exakter Wert

Gleiches Spiel selbstverständlich, wenn ich den Wert per PHP aus der Datenbank heraushole.

Weitere Posts:

Dieser Beitrag wurde unter php, Datenbanken, webdev veröffentlicht. Setze ein Lesezeichen auf den Permalink.

4 Antworten auf MySQL: Spaß mit float

  1. Oliver sagt:

    Ja, float sollte eh nicht in mysql benutzt werden, weil es nur eine (ODBC) Hilfsfunktion ist. Wenn Du float mit einem Wert zwischen 25 und 53 benutzt, sollte das Gleiche raus kommen. Warum natürlich zwei Ausgaben raus kommen, leuchtet mir gerade auch nicht ein.

  2. Jannik sagt:

    Das hat folgende Erklärung:

    die Fließkommazahlen in MySQL sind über den IEEE 754 implementiert.

    und das Problem liegt grundlegend daran, dass 1e15 nicht im Wertebereich des Floats liegt.
    1e15 hat 34 signifikante Stellen, jedoch sind die Mantissen-Breiten wie folgt:

    FLOAT: 23
    DOUBLE: 52
    (hängt von Hardware und Konfiguration ab, das sind jetzt die Werte der Spezifikation)

    D.h. die 1e15 könnte so oder so nicht in dem FLOAT ohne Rundung gespeichert werden. MySQL schluckt dies wohl allerdings.

    Sobald du allerdings mit 1 multiplizierst, wird auf der Server-Hardware eine Floating Point Multiplikation ausgeführt – der Wert ist allerdings zu groß, weswegen er gerundet wird.

    Wenn wir uns nun den Wert mal genau ansehen, sehen wir, dass
    999999986991104 binär dargestellt so aussieht:
    11100011010111111010100100000000000000000000000000

    Was genau:
    „1.“ (23 Stellen Mantisse) + Exponent 2^x ist

    Mehr Stellen (was du für 1e15 bräuchtest) passen nicht in den Datentyp, d.h. man bekommt Rundungsfehler.

    PS: in deinem Beispielcode verwendest du 1e11, die Ausgabe ist jedoch 1e15…
    PPS: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html

    1. david sagt:

      Danke für den hervorragenden Kommentar und die Aufklärung.

      Habe den Code eben korrigiert.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert