【问题标题】:Can FLOAT types be truncated in MySQL stored functions?可以在 MySQL 存储函数中截断 FLOAT 类型吗?
【发布时间】:2019-06-05 18:28:25
【问题描述】:

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

我正在编写一个存储函数,我需要在其中将浮点数截断到一定数量的小数位。据我了解,内置的 TRUNCATE 函数应该为我执行此操作;但是,我得到的结果根本没有被截断。唯一值得注意的变化是预期截断点之后的一些数字与原始数字不同。

我已经尝试过使用相同的数字(原始)单独使用 truncate 函数,即。 SELECT TRUNCATE(0.00123456, 5) AS 'Example',这和预期的一样。我感觉存储函数中的问题与在 truncate 函数中用作参数的浮点类型有关。

我应该注意到,我首先截断这个数字的原因是因为 round 函数未能按预期截断小数位数。我在这里解释了更多(并以实际函数为例):What is the proper if clause syntax for a MySQL stored function?,但为了清楚起见,我在下面包含了一些精简的代码。

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。

truncate 与 FLOAT 类型不兼容有什么原因吗?还是我在这里缺少其他东西?

【问题讨论】:

    标签: mysql floating-point truncate


    【解决方案1】:

    是的,它们不兼容。

    FLOAT 以 IEEE-754 二进制格式存储数据,以 2 为基数存储。以 10 为基数的分数不完全适合。因此,您的函数获得接近 0.0012345 的截断值,但 FLOAT 不能保持精确,因此您获得所需的数字。 请参阅here 和其他地方的许多答案,尤其是What Every Computer Scientist Should Know About Floating-Point Arithmetic,了解 IEEE 格式浮点数的表示形式。

    如果你想要精确的小数位数,你需要使用DECIMAL 类型

    【讨论】:

    • 啊,我明白了。谢谢你的回答,这很有意义!为了澄清,你建议我在这种情况下使用十进制类 - 在声明一个总位数未知且小数点后位数未知的十进制变量方面,这将如何工作?
    猜你喜欢
    • 2010-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-05
    • 1970-01-01
    • 2017-08-29
    • 2019-06-24
    • 2016-09-05
    相关资源
    最近更新 更多