MySQL 使用 FLOOR 会导致意外结果

MySQL 使用 FLOOR 会导致意外结果

在 MySQL 中我有以下公式:

SELECT FLOOR(38774/184*126*23+0.5);

令我惊讶的是610690,即使公式内部的结果为,它也能产生结果。在 Excel 中,这可以正常工作并给出我想要的结果,在我使用的 macOS 或 Windows 上的任何计算器中也是如此。FLOOR610691

我是不是忽略了什么?这种行为有什么解释吗?更重要的是,我该如何防止这种情况发生?

答案1

浮点计算是一件很有趣的事情:试试这些:

SELECT FLOOR(38774/184*126*23+0.5);
SELECT FLOOR(38774*126*23/184+0.5);
SELECT FLOOR(ROUND(38774/184*126*23+0.5, 3));

这里发生了什么?

最重要的部分是,它38774/184没有浮点数的准确表示 - 你总是会少一点点。其余计算加起来正好是 610691,最终你会比 610691 少一点点,从而得到FLOOR610690。

第二行通过将计算的各个部分重新组合为一个序列来避免这种情况,该序列确实具有浮点数的精确表示。

第三行使用 来ROUND截断非常小的差异,从而使FLOOR工作符合预期。

经验法则:浮点数不会产生精确的结果。虽然它们通常“足够精确”,但也有不精确的极端情况。你只需遇到一个相当常见的情况:通过FLOOR或转换回整数CEIL

现在回答你的问题:根据我的经验,我会按照第二行的方式进行计算 - 更大的数字(在 INT32 范围内)更有可能产生正确的结果FLOOR。如果计算成本对你来说是可以接受的,我会选择

SELECT FLOOR(ROUND(38774*126*23/184+0.5, 3));

并且非常有信心涵盖所有边缘情况。

相关内容