在 MySQL 中我有以下公式:
SELECT FLOOR(38774/184*126*23+0.5);
令我惊讶的是610690
,即使公式内部的结果为,它也能产生结果。在 Excel 中,这可以正常工作并给出我想要的结果,在我使用的 macOS 或 Windows 上的任何计算器中也是如此。FLOOR
610691
我是不是忽略了什么?这种行为有什么解释吗?更重要的是,我该如何防止这种情况发生?
答案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 少一点点,从而得到FLOOR
610690。
第二行通过将计算的各个部分重新组合为一个序列来避免这种情况,该序列确实具有浮点数的精确表示。
第三行使用 来ROUND
截断非常小的差异,从而使FLOOR
工作符合预期。
经验法则:浮点数不会产生精确的结果。虽然它们通常“足够精确”,但也有不精确的极端情况。你只需遇到一个相当常见的情况:通过FLOOR
或转换回整数CEIL
。
现在回答你的问题:根据我的经验,我会按照第二行的方式进行计算 - 更大的数字(在 INT32 范围内)更有可能产生正确的结果FLOOR
。如果计算成本对你来说是可以接受的,我会选择
SELECT FLOOR(ROUND(38774*126*23/184+0.5, 3));
并且非常有信心涵盖所有边缘情况。