我知道在mysql中将十进制值存储为float是一个坏主意。
示例:如果我存储了一个价格为$ 5.01的产品,该数字没有精确的浮点类型表示。
如果你这样做:
CREATE TABLE IF NOT EXISTS `test` (
`test` float NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO `test` (`test`) VALUES
(5.01);
然后运行查询
SELECT AVG( test )
FROM test
对着桌子,你会得到这个:
mysql> select avg(test) from test;
+------------------+
| avg(test) |
+------------------+
| 5.01000022888184 |
+------------------+
1 row in set (0.00 sec)
但是如果你只选择像这样的字段:
mysql> select * from test;
+------+
| test |
+------+
| 5.01 |
+------+
1 row in set (0.00 sec)
你最终会得到正确的金额。
我的问题是:这怎么可能?
如果float类型不能准确地表示我的值?
不应该选择返回5.01000022888184 ?
普通选择返回5.01的原因是它是比任何其他浮点数更接近实际值的最短数字;MySQL显示这个结果,而不是将实际值转换回最接近的小数,因为在大多数情况下,用户会认为这个结果"更正确"。
avg()
表现不同的原因可能是它使用double
进行计算,而5.01当然不是比所有double
值更接近四舍五入到- float
的实际值,因为这些值多得多。
我认为这就像数据库存储数字一样简单但是一旦你操纵它,它就会在IEEE 754形式中使用
参见前面的问题(oracle相关)oracle Floats vs Number
真正的问题是你不能这样做:
SELECT * FROM `test` WHERE `test` = 5.01
MySQL中存储的float的值为unknowable
这是一个巨大的错误,但是他们不愿意修复它。Decimal和Double也有类似的问题。唯一的修复方法是为模式
中的字段指定精确的精度。ALTER TABLE `test` change `test` `test` FLOAT(10,2)
但是在计算精度不太明确的地方(例如:任何分数)