Bug in MySQL - FLOAT-Wert in IF()-Funktion

26 Mar 2011 um 14:54 - MySQL/Datenbank

Vor 2 Tagen habe ich einen Bug in MySQL entdeckt und ich bin sehr stolz darauf :) Mir gefällt die verschiedenen komplizierten Abfragen zu basteln und eine davon hat versagt...

Die Ergebnisse der Abfrage wurden im Formular einem hidden-Element zugewiesen und dieser Wert soll dann mit anderen verglichen werden usw. Mit den ganzen Zahlen hat es einwandfrei funktioniert, aber mit FLOAT-Wert bekam ich die falschen Ergebnissen. Das liegt daran, dass ich in IF()-Funktion die Werte von Typ FLOAT verwendet haben. Und ein Fehler tritt auf nur dann, wenn der Fließkommawert bearbeitet wird.

Hier ist das Beispiel dazu. Erzeugen wir eine Tabelle mit 3 Spalten: FLOAT_VALUE (Typ "FLOAT"), REAL_VALUE (Typ "REAL") und DOUBLE_VALUE (Typ "DOUBLE"):

 CREATE TABLE `TEXAMPLE` (
`FLOAT_VALUE` FLOAT,
`REAL_VALUE` REAL,
`DOUBLE_VALUE` DOUBLE)

Dann noch 2 Datensätze anlegen - 1. Datensatz mit dem Ganzzahlwert und andere mit dem Fließkommawert:

 INSERT INTO TEXAMPLE (`FLOAT_VALUE`, `REAL_VALUE`, `DOUBLE_VALUE`) 
VALUES (1, 1, 1), (1.3, 1.3, 1.3);

Jetzt kommt IF()-Funktion ins Spiel (Bemerkung: IF()-Funktion in MySQL ist nicht einfache IF-Anweisen):

 SELECT 
FLOAT_VALUE, IF(TRUE,FLOAT_VALUE,0) AS IF_FLOAT,
REAL_VALUE, IF(TRUE,REAL_VALUE,0) AS IF_REAL,
DOUBLE_VALUE, IF(TRUE,DOUBLE_VALUE,0) AS IF_DOUBLE
FROM TEXAMPLE

Und die Ergebnisse:

Wie man sieht, wird der FLOAT-Wert in IF()-Funktion noch "genauer" ;) Man könnte sagen, dass es sich hier um die Probleme mit Fließkommavergleichen handelt, aber die REAL- und DOUBLE-Werte werden hier richtig dargestellt und außerdem wird nichts verglichen, sondern nur direkt ohne Bearbeitung ausgegeben.

Hier ist die Beschreibung aus Doku:

 IF(expr1,expr2,expr3)
Wenn expr1 TRUE ist (expr1<> 0 und expr1 <> NULL), dann gibt IF() expr2 zurück;
andernfalls gibt es expr3 zurück.
IF() gibt je nach Verwendungskontext einen numerischen oder einen String-Wert zurück.

Deshalb sollte hier als Ergebnis

 IF(TRUE,FLOAT_VALUE,0) => FLOAT_VALUE
und wenn wir unseren Datensatz mit 1.3 nehmen dann bekommen wir
1.29999995231628 statt 1.3

Wahrscheinlich konvertiert IF()-Funktion jeden FLOAT-Wert in REAL bzw. DOUBLE (so wird der Wert noch genauer). In der Dokumentation steht dazu nichts, aber jetzt wissen wir, wie es funktioniert :)

P.S. Alles wurde mehrmals getestet mit MySQL 5.1 unter Windows.

P.S.S. Vielleicht geht es hier um keinen richtigen Bug, aber das sollte als Kommentar in Doku rein.

Kommentare (2)

offlaner hat geschrieben am 27 Mar 2011 um 22:40
±0

Gut gemacht! Es erinnert mich das Pentium FDIV Problem.

Markus hat geschrieben am 9 Jun 2011 um 15:16
±0

genau mein Problem, danke für die Lösung!


© 2008 Anton Pavlushko - Webentwicklung, Internetmarketing und Suchmaschinenoptimierung (SEO)

0.0067110061645508 sec