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

mat*_*teo 12 mysql floating-point-precision

UPDATE some_table SET some_float_field=1919.987 WHERE id=123

SELECT * FROM some_table WHERE id=123
Run Code Online (Sandbox Code Playgroud)

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

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

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

Gor*_*off 12

运行查询时:

SELECT * FROM some_table WHERE id = 123
Run Code Online (Sandbox Code Playgroud)

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

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

select format(some_float_field, 3)
Run Code Online (Sandbox Code Playgroud)

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

select cast(some_float_field as decimal(8, 3))
Run Code Online (Sandbox Code Playgroud)

也应该做的伎俩.

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

select *
from some_table
where some_float_field between 1919.987 - 0.0001 and 1919.987 + 0.0001;
Run Code Online (Sandbox Code Playgroud)

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


Kai*_*aii 10

来自手册FLOAT:

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

这里的重点在于近似.如果需要存储确切的值,则应该使用DECIMAL数据类型.

因为FLOAT,MySQL使用IEEE标准754进行二进制浮点运算,将一个数字的任意部分"压缩"为4个字节(或者,对于DOUBLE,为8).

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

维基百科很好地解释了浮点的概念.

请注意,该算法受列定义中指定的精度影响.
请参阅此SQL小提琴示例.

  • 我认为我的问题非常明确,因为我知道浮点数是多少,并且它具有精度和误差.我的问题是为什么精度低于预期.http://www.h-schmidt.net/FloatConverter/IEEE754.html如果我将1919.987转换为ieee 754并返回我没有收到任何错误 (3认同)
  • 是的,问题是精度足以区分 1919.987 和 1919.99,因此这并不能解释为什么这两个值最终会被视为相同。戈登的回答解释了什么 (2认同)