MySQL Round()函数用于存储在字符串中的十进制

Dav*_*mov 6 mysql sql floating-point numbers

MySQL版本是5.66.22

当我ROUND对存储在varchar中的十进制数字使用函数时,我看到所有.5数字的奇怪行为

Select round(0.5)
1

Select round('0.5')
0

Select round('26.5' + 0.00)
26
Run Code Online (Sandbox Code Playgroud)

Select round(1.5)
2

Select round('1.5')
2

Select round(0.55, 1)
0.6

Select round('0.55', 1)
0.6
Run Code Online (Sandbox Code Playgroud)

我在Oracle DB(12c)中检查了ROUND函数,它按预期工作

Select round('0.5') from dual 
1

Select round(0.5) from dual 
1
Run Code Online (Sandbox Code Playgroud)

有人知道如何解释吗?

所描述的mysql round()函数行为在应用程序中引起“取整”问题。为了解决这个问题,我使用:

Select round (CAST('0.5' AS DECIMAL(10,2)))
1
Run Code Online (Sandbox Code Playgroud)

我知道将数字存储在varchar中是不好的设计,但是此应用程序是很久以前编写的,现在没有人想要重构代码

Sal*_*n A 5

有趣的。该行为可以解释如下:

1) MySQL 在数字上下文 ( ref ) 中使用时将字符串转换为浮点值:

CREATE TABLE test AS (
    SELECT 0.5, '0.5' * 1 AS str_to_numeric
);

DESCRIBE test;

+----------------+--------------+------+-----+---------+-------+
| Field          | Type         | Null | Key | Default | Extra |
+----------------+--------------+------+-----+---------+-------+
| 0.5            | decimal(2,1) | NO   |     | 0.0     |       |
| str_to_numeric | double       | NO   |     | 0       |       |
+----------------+--------------+------+-----+---------+-------+
Run Code Online (Sandbox Code Playgroud)

2)如手册中所述:

舍入行为

ROUND()函数根据其参数是精确的还是近似的进行不同的舍入:

  • 对于精确值数字,ROUND()使用“四舍五入”规则:小数部分为 0.5 或更大的值如果为正则向上舍入到下一个整数,如果为负则向下舍入到下一个整数。(换句话说,它从零开始舍入。)小数部分小于 0.5 的值如果为正则向下舍入到下一个整数,如果为负则向上舍入到下一个整数。

  • 对于近似值数字,结果取决于 C 库。在许多系统上,这意味着ROUND()使用“四舍五入到最接近的偶数”规则:具有任何小数部分的值四舍五入到最接近的偶数。

以下是一些说明 ROUND 函数最终行为的测试:

CREATE TABLE test(
   fix DECIMAL(10,2),
   arb DOUBLE
);

INSERT INTO test(fix, arb) VALUES
    (0.5, 0.5),
    (1.5, 1.5),
    (2.5, 2.5),
    (3.5, 3.5);

SELECT fix, ROUND(fix) fix_roundex, arb, ROUND(arb) arb_rounded
FROM test

+------+-------------+------+-------------+
| fix  | fix_roundex | arb  | arb_rounded |
+------+-------------+------+-------------+
| 0.50 |           1 |  0.5 |           0 |
| 1.50 |           2 |  1.5 |           2 |
| 2.50 |           3 |  2.5 |           2 |
| 3.50 |           4 |  3.5 |           4 |
+------+-------------+------+-------------+
Run Code Online (Sandbox Code Playgroud)

您的解决方案,将数字字符串显式转换为DECIMAL,是正确的。

  • 是的。您所说的是“四舍五入到最接近的偶数”的另一种说法……避免最后一位数字为奇数。 (2认同)