在编写科学应用功能时,我遇到了问题.我追溯到MySQL缺乏精确性.
这里有可重现的代码(一个mysql存储函数)来测试它 –DELIMITER $$
DROP FUNCTION IF EXISTS test$$
CREATE FUNCTION test
(xx DECIMAL(30,25)
)
RETURNS DECIMAL(30,25)
DETERMINISTIC
BEGIN
DECLARE result DECIMAL(30,25);
SET result = 0.339946499848118887e-4;
RETURN(result);
END$$
DELIMITER ;
如果将上面的代码保存在名为test.sql的文件中,则可以通过在mysql提示符中执行以下命令来运行它 –source test.sql;
select test(0);
它产生输出 –-----------------------------
| test(0) |
-----------------------------
| 0.0000339946499848118900000 |
-----------------------------
1 row in set (0.00 sec)
正如您所看到的,数字在第20位被舍入,然后在其中添加了5个零以达到所需/指定的精度.那是作弊.
我错了,还是文件错了?
解决方法:
我对SQL一无所知,但我的猜测是这一行:SET result = 0.339946499848118887e-4;
如果MySQL与我所知道的其他语言类似,那么这将首先评估右侧,然后将值赋给结果.无论声明什么类型的结果或声明具有什么精度,如果右侧在评估时已经失去了精度,则无关紧要.这几乎肯定是这里发生的事情.
我可以重现你的结果,但如果我改变那条线SET result = cast('0.339946499848118887e-4' as decimal(30, 25));
(从一个字符串而不是从未指定精度的浮点常量中转换)然后我正确得到-----------------------------
| test(0) |
-----------------------------
| 0.0000339946499848118887000 |
-----------------------------
1 row in set (0.00 sec)
如预期的.这就是你的修复.
顺便说一下,在DECIMAL(精度,比例)中缩放的文档不能大于30,似乎在12.19.2. DECIMAL Data Type Changes节中:The declaration syntax for a DECIMAL column is DECIMAL(M,D). The
ranges of values for the arguments in MySQL 5.6 are as follows:
M is the maximum number of digits (the precision). It has a range of 1
to 65. (Older versions of MySQL permitted a range of 1 to 254.)
D is the number of digits to the right of the decimal point (the
scale). It has a range of 0 to 30 and must be no larger than M.