mysql - 可以在 MySQL 存储函数中截断 FLOAT 类型吗?
问题描述
我是 MySQL 和存储函数的新手,所以如果这个问题看起来很简单,我深表歉意。
我正在编写一个存储函数,其中我需要将浮点数截断到一定数量的小数位。据我了解,内置的 TRUNCATE 函数应该为我执行此操作;但是,我得到的结果根本没有被截断。唯一值得注意的变化是预期截断点之后的一些数字与原始数字不同。
我已经尝试使用相同的数字(原始)自行尝试 truncate 函数,即。SELECT TRUNCATE(0.00123456, 5) AS 'Example',这和预期的一样。我感觉存储函数中的问题与在 truncate 函数中用作参数的浮点类型有关。
我应该注意到,我首先截断这个数字的原因是因为 round 函数未能按预期截断小数位数。我在这里解释更多(并以实际函数为例):MySQL 存储函数的正确 if 子句语法是什么?,但为了清楚起见,我在下面包含了一些精简的代码。
CREATE FUNCTION 'sfround'(number FLOAT, sigFigs INT) RETURNS FLOAT
DETERMINISTIC
BEGIN
DECLARE nonTruncated FLOAT;
DECLARE truncated FLOAT;
DECLARE decimalsKept INT;
#some not relevant code in the middle
SET nonTruncated = ROUND(number, sigFigs-1-FLOOR(LOG10(ABS(number))));
SET truncated = TRUNCATE(nonTruncated, decimalsKept);
RETURN truncated;
END$$
当我的输入是 1 到 -1 之间的任何数字(不包括 0,因为我包含了处理 0 的边缘情况)时,此函数会产生一个正确的数字,直到预期的截断点,之后看似不相关的数字列表出现(每次调用函数的数字相同)。
前任。sfround(0.00123456, 5) 产生 0.0012344999704509974。
截断与 FLOAT 类型不兼容有什么原因吗?还是我在这里缺少其他东西?
解决方案
是的,它们不兼容。
FLOAT 以 IEEE-754 二进制格式存储数据,该格式存储在基数 2 中。基数为 10 的分数不完全适合。因此,您的函数获得接近 0.0012345 的截断值,但 FLOAT 不能保持精确,因此您获得所需的数字。请参阅此处和其他地方的许多答案,尤其是每个计算机科学家应该知道的关于浮点运算的知识,以了解 IEEE 格式浮点数的表示形式。
如果你想有一个确切的小数位数,你需要使用DECIMAL类型
推荐阅读
- webpack - 如何使用 CRA + 代码拆分避免块中的重复代码
- javascript - Froala Font-Size Popup 方向错误
- javascript - reactjs:每次更改reducer时重新渲染屏幕的一部分
- c++ - 为什么不显示三角形?
- ibm-watson - Watson Assistant 查询
- c# - 绑定到自定义控件的依赖属性
- swift - 为什么我的阴影在 SceneKit 中像素化/断断续续?
- winapi - WinAPI 中是否有与 GLFW 的 glfwGetWindowUserPointer 等效的函数?
- javascript - PHP Post 在 POST 中 - 使用 Javascript 提交表单
- azure - 为 AZURE ubuntu VM 添加新的 SSH 用户帐户