我知道在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吗?
答案 0 :(得分:1)
我认为它就像数据库存储数字一样简单,但是一旦你操作它,它就会用在IEEE 754表格中
查看之前的(与oracle相关的)问题Oracle Floats vs Number
答案 1 :(得分:1)
普通选择返回5.01的原因是它是最接近实际值的最短数字而不是任何其他浮点数; MySQL显示此而不是将实际值转换回最接近的小数部分,因为在大多数情况下,用户会将此结果视为“更正确”。
avg()
行为不同的原因可能是它使用double
进行计算,而5.01当然不更接近舍入到 - {{1实际值比所有float
值都要多,因为其中有更多值。
答案 2 :(得分:0)
真正的问题是你无法做到:
SELECT * FROM `test` WHERE `test` = 5.01
存储在MySQL中的浮点值是 unknowable
这是一个巨大的错误,但他们不愿意修复它。 Decimal和Double有类似的问题。唯一的解决方法是为架构中的字段指定精确的精度
ALTER TABLE `test` change `test` `test` FLOAT(10,2)
但是你在计算精度不太明确的地方(例如任何分数)时会失去任何精度