我是MySQL的新成员,并且是存储函数,所以如果这个问题很简单,我深表歉意。
我正在编写一个存储函数,在其中需要将浮点数截断为一定的小数位数。据我了解,内置的TRUNCATE函数应该为我完成此操作;但是,我得到的结果并没有被截断。唯一值得注意的变化是,在预期的截断点之后的一些数字与原始数字不同。
我已经尝试过用相同的数字(原始)来尝试truncate函数。 SELECT TRUNCATE(0.00123456,5)作为“示例”,并且可以按预期工作。我感觉到我的存储函数存在问题,这与将float类型用作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。
是否有某些原因导致截断与FLOAT类型不兼容?还是在这里我想念其他东西?
答案 0 :(得分:0)
是的,它们不兼容。
FLOAT以IEEE-754二进制格式存储数据,该格式存储在基数2中。基数10的分数不能完全适合。因此,对于截断,您的函数将获得接近0.0012345的值,但是FLOAT无法保持该精确值,因此您获得了所需的数字。 有关IEEE格式浮点数表示什么的信息,请参见here和其他地方,尤其是What Every Computer Scientist Should Know About Floating-Point Arithmetic的答案。
如果要精确地保留小数位数,则需要使用DECIMAL类型