可以在MySQL存储函数中截断FLOAT类型吗?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (1)
  • 关注 (0)
  • 查看 (10)

我是MySQL和存储函数的新手,所以如果这个问题看起来很简单,我会道歉。

我正在编写一个存储函数,我需要将float截断到一定数量的小数位。据我了解,内置的TRUNCATE函数应该为我做这个; 但是,我得到的结果根本没有被截断。唯一明显的变化是预期截断点之后的某些数字与原始数字不同。

我尝试用自己的截断函数用相同的数字(原始)进行试验,即。SELECT TRUNCATE(0.00123456,5)AS'示例',并且按预期工作。我有一种感觉,我在存储函数中的问题与浮点类型有关,它被用作截断函数中的参数。

我应该注意到,我首先截断这个数字的原因是圆函数未能按预期切断小数的结果。我在这里解释了更多(并以实际函数为例):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类型不兼容?或者还有其他我在这里缺少的东西?

提问于
用户回答回答于

是的,他们是不相容的。

FLAOT以IEEE-754二进制格式存储数据,该格式存储在基数2中。基数10分数不完全适合。因此,你的函数在截断时会得到接近0.0012345的值,但是FLOAT不能保持那么精确,所以你得到了所需的数字。请参阅此处和其他地方的许多答案,尤其是每个计算机科学家应该知道的关于浮点算术的内容,IEEE格式的浮点数表示为什么。

如果要获得精确的小数位数,则需要使用DECIMAL类型

扫码关注云+社区

领取腾讯云代金券