为什么MySQL循环浮动的方式比预期的要多?

时间:2014-04-16 21:34:54

标签: mysql floating-point-precision

UPDATE some_table SET some_float_field=1919.987 WHERE id=123

SELECT * FROM some_table WHERE id=123

其中some_float_field是一个定义为“float”的字段(没有任何特定的大小值)。

预期结果值为1919.987;相反,它被舍入到1919.99

为什么呢? 32位(单精度)浮点数具有足够的精度,可以正确存储!

2 个答案:

答案 0 :(得分:10)

来自FLOAT的手册:

  

FLOATDOUBLE类型代表近似数字数据值。 MySQL使用四个字节作为单精度值..

这里的重点在于 近似 。如果您需要存储完全值,则应该使用DECIMAL数据类型。

FLOATMySQL uses the IEEE standard 754 for binary floating point arithmetic to "compress" any fraction of a number into 4 bytes (or 8, for DOUBLE)

请注意,这适用于任何值,无论值(小数部分和小数) 能够以4个字节精确表示!例如,浮点数0.01的表示正好是0.009999999776482582092285156250 - 即使0.01使用另一种存储格式完全适合32位内存。

Wikipedia explains the concept of floating point pretty well

请注意,算法受列定义中指定的精度影响。
See this SQL fiddle example.

答案 1 :(得分:10)

运行查询时:

SELECT * FROM some_table WHERE id = 123

您依靠用户界面来格式化浮点数。您正在使用的界面使用两个字符而不是更多。毕竟,没有关于"权利"的信息。要显示的数字。

您可以通过将数字格式化为字符串或小数来说服界面显示正确的数字。例如:

select format(some_float_field, 3)

会将此转换为带有三个小数位的字符串。一个警告:它还会添加你可能不想要的逗号。这也应该有效:

select cast(some_float_field as decimal(8, 3))

也应该这样做。

请注意,您可以通过执行以下操作来轻松验证数据是否正确:

select *
from some_table
where some_float_field between 1919.987 - 0.0001 and 1919.987 + 0.0001;

请注意,您不希望在浮点值上使用=,但您已经明白了。