关于MySQL的ROUND函数四舍五入的细节分析
引子
在群里,有人问了这么一个问题,引起了我的兴趣。查询之后感觉打开了新世界的大门,因此记录一下,以作备忘(MySQL版本:5.7.17-log)。
#执行:
SELECT ROUND(1.3225, 3);
#结果:
1.323
#执行:
SELECT ROUND('1.3225', 3);
#结果:
1.322
MySQL的ROUND()函数:
ROUND(X)或ROUND(X,D),简单来说作用是返回X四舍五入到小数点后第D位(默认0)的值,即:
#执行:
SELECT ROUND(-1.23);
#结果:
-1
#执行:
SELECT ROUND(1.298, 1);
#结果:
1.3
回到上面的问题,为什么看似相同的语句执行出来的结果不同,其实可以从官方文档[1]中找到端倪(以下是我自己的翻译,如果有误谢谢指出):
ROUND() uses the following rules depending on the type of the first
argument:
ROUND()根据第一个参数的类型来应用以下(不同)的规则:
For exact-value numbers, ROUND() uses the “round half away from zero”
or “round toward nearest” rule: A value with a fractional part of .5
or greater is rounded up to the next integer if positive or down to
the next integer if negative. (In other words, it is rounded away from
zero.) A value with a fractional part less than .5 is rounded down to
the next integer if positive or up to the next integer if negative.
对于精确值的数字,ROUND()使用”中间值朝远离0点方向舍入“或”朝最近舍入“规则:一个小数部分为.5或更大的值,若为正则向上舍入,若为负则向下舍入。(换而言之,就是向远离0的方向舍入。)一个小数部分小于.5的值,若为正则向下舍入,若为负则向上舍入。
For approximate-value numbers, the result depends on the C library. On
many systems, this means that ROUND() uses the “round to nearest even”
rule: A value with a fractional part exactly halfway between two
integers is rounded to the nearest even integer.
对于近似值的数字,返回结果取决于C库。在许多系统中,这意味着ROUND()使用”舍入最接近的偶数“规则:一个值的小数部分正好在两个整数中间时,舍入到最接近的偶数。
解答
根据以上规则,我们可以推断,MySQL自动将‘1.3225’这个字符串转换为了一个近似值数字。
那么,在MySQL中(仅针对MySQL 5.7),哪些数值型数据类型对应的是精确值的数字呢,以下就是答案:
1)整型:INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT
2)定点型:DECIMAL, NUMERIC
值得注意的是,浮点型并不在列,这也就是为什么会出现开头问题的原因。