hnwの日記

MySQLのFLOAT型を使う理由が見つからない件


MySQLFLOAT


MySQL6FLOAT使FLOAT使


MySQLCMySQL


MySQLのFLOAT型とは


MySQLFLOATIEEE75432bit*1MySQL




FLOAT  DOUBLE MySQL 48使


https://dev.mysql.com/doc/refman/5.6/ja/floating-point-types.html
 


Cfloat


不思議な挙動(1):+0すると見た目の値が変わる


MySQLFLOAT使MySQL5.7.20


mysql> CREATE TABLE a (fFLOAT, d DOUBLE);
Query OK, 0 rows affected (0.03 sec)

mysql> INSERT INTOaVALUES(0.9,0.9);
Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM a;
+------+------+
| f    | d    |
+------+------+
|  0.9 |  0.9 |
+------+------+
1 row in set (0.00 sec)


FLOATDOUBLE0.9SELECT0.9


0


mysql> SELECT f+0,d+0 FROM a;
+--------------------+------+
| f+0                | d+0  |
+--------------------+------+
| 0.8999999761581421 |  0.9 |
+--------------------+------+
1 row in set (0.00 sec)


FLOAT0.9+00.8999999761581421IEEE7540.9FLOAT


d+00.9d0.9MySQLDOUBLE10MySQL




dtoa 使D DECIMAL F (IEEE) 


F -> D FDIEEE 


https://dev.mysql.com/doc/refman/5.6/ja/type-conversion.html
 


10FLOATDOUBLEQiitaFLOAT106便


不思議な挙動(2):INSERTした値がWHERE句の検索条件に使えない


使WHERE


mysql> SELECT * FROMaWHERE f=0.9;
Empty set (0.00 sec)

mysql> SELECT * FROMaWHERE d=0.9;
+------+------+
| f    | d    |
+------+------+
|  0.9 |  0.9 |
+------+------+
1 row in set (0.00 sec)


fdINSERT0.9WHERE0.9使0.9FLOAT1


DOUBLE*2f0.8999999761581421DOUBLE0.90.900000000000000022DOUBLEINSERTSELECTDOUBLE


FLOATFLOATDOUBLE


mysql> SELECT * FROMaWHERE f=0.8999999761581421;
+------+------+
| f    | d    |
+------+------+
|  0.9 |  0.9 |
+------+------+
1 row in set (0.00 sec)


MySQLDOUBLEFLOATFLOATDOUBLE


不思議な挙動(3):同じ値に見えても別の値のことがある


b2INSERT


mysql> CREATE TABLE b (f1 FLOAT, f2 FLOAT);
Query OK, 0 rows affected (0.04 sec)

mysql> INSERT INTObVALUES(0.9,0.8999996);
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTObVALUES(0.9,0.89999996);
Query OK, 1 row affected (0.01 sec)

mysql> SELECT * FROM b;
+------+------+
| f1   | f2   |
+------+------+
|  0.9 |  0.9 |
|  0.9 |  0.9 |
+------+------+
2 rows in set (0.00 sec)


0.90.92INSERT0.9


mysql> SELECT * FROMbWHERE f1=f2;
+------+------+
| f1   | f2   |
+------+------+
|  0.9 |  0.9 |
+------+------+
1 row in set (0.00 sec)

mysql> SELECT f1+0,f2+0 FROM b;
+--------------------+--------------------+
| f1+0               | f2+0               |
+--------------------+--------------------+
| 0.8999999761581421 | 0.8999996185302734 |
| 0.8999999761581421 | 0.8999999761581421 |
+--------------------+--------------------+
2 rows in set (0.00 sec)


f1f2SELECT10.899999960.9FLOAT0.8999996


SELECT * FROM bFLOATSELECTUPDATE


MySQLstrings/dtoa.cmy_gcvtFLOATmy_gcvtFLOATFLT_DIG


  res= dtoa(x, 4, type == MY_GCVT_ARG_DOUBLE ? width : MY_MIN(width, FLT_DIG),
            &decpt, &sign, &end, buf, sizeof(buf));


FLT_DIGCfloat106FLOATFLT_DIG+2FLOAT10





FLOATOSS使FLOATFLOAT


DOUBLEDOUBLESELECT101:110


まとめ


MySQLFLOAT




FLOAT

f+0DOUBLE


FLOATDOUBLE

FLOATSELECT1:1

FLOAT




FLOAT







DECIMAL使

1000MySQL

10



2DOUBLE

*1:FLOAT(25)のように精度指定した場合は倍精度型になることもあります

*2:MySQLマニュアル上でこれに関する記述は見当たりませんが、実質的には仕様に近いように感じています