Documentation Home
MySQL 8.0 参考手册  / 第 12 章函数和运算符  / 12.25 精密数学  /  12.21.5 精度数学示例

12.21.5 精度数学示例

本节提供一些示例,显示 MySQL 中的精确数学查询结果。这些示例演示了第 12.21.3 节“表达式处理”第 12.21.4 节“舍入行为”中描述的原则。

示例 1。在可能的情况下使用数字及其精确值:

mysql> SELECT (.1 + .2) = .3;
+----------------+
| (.1 + .2) = .3 |
+----------------+
|              1 |
+----------------+

对于浮点值,结果不准确:

mysql> SELECT (.1E0 + .2E0) = .3E0;
+----------------------+
| (.1E0 + .2E0) = .3E0 |
+----------------------+
|                    0 |
+----------------------+

另一种查看精确值和近似值处理差异的方法是多次将一个小数加到总和中。考虑以下存储过程,它 .0001向变量添加 1,000 次。

CREATE PROCEDURE p ()
BEGIN
  DECLARE i INT DEFAULT 0;
  DECLARE d DECIMAL(10,4) DEFAULT 0;
  DECLARE f FLOAT DEFAULT 0;
  WHILE i < 10000 DO
    SET d = d + .0001;
    SET f = f + .0001E0;
    SET i = i + 1;
  END WHILE;
  SELECT d, f;
END;

d逻辑上和 的总和f 应为 1,但这仅适用于小数计算。浮点计算引入了小错误:

+--------+------------------+
| d      | f                |
+--------+------------------+
| 1.0000 | 0.99999999999991 |
+--------+------------------+

示例 2。乘法以标准 SQL 所需的比例执行。也就是说,对于两个数字X1X2具有规模 S1S2,结果的规模是: S1 + S2

mysql> SELECT .01 * .01;
+-----------+
| .01 * .01 |
+-----------+
| 0.0001    |
+-----------+

示例 3。精确值数字的舍入行为是明确定义的:

舍入行为(例如, ROUND()函数)独立于底层 C 库的实现,这意味着结果在平台之间是一致的。

  • 精确值列(DECIMAL和整数)和精确值数字的舍入使用从零舍入一半规则。小数部分为 .5 或更大的值从零四舍五入到最接近的整数,如下所示:

    mysql> SELECT ROUND(2.5), ROUND(-2.5);
    +------------+-------------+
    | ROUND(2.5) | ROUND(-2.5) |
    +------------+-------------+
    | 3          | -3          |
    +------------+-------------+
  • 浮点值的舍入使用 C 库,它在许多系统上使用舍入到最接近的偶数 规则。小数部分正好在两个整数中间的值四舍五入到最接近的偶数:

    mysql> SELECT ROUND(2.5E0), ROUND(-2.5E0);
    +--------------+---------------+
    | ROUND(2.5E0) | ROUND(-2.5E0) |
    +--------------+---------------+
    |            2 |            -2 |
    +--------------+---------------+

例 4。在严格模式下,插入一个超出列范围的值会导致错误,而不是截断为合法值。

当 MySQL 未在严格模式下运行时,将截断为合法值:

mysql> SET sql_mode='';
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TABLE t (i TINYINT);
Query OK, 0 rows affected (0.01 sec)

mysql> INSERT INTO t SET i = 128;
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql> SELECT i FROM t;
+------+
| i    |
+------+
|  127 |
+------+
1 row in set (0.00 sec)

但是,如果严格模式生效,则会发生错误:

mysql> SET sql_mode='STRICT_ALL_TABLES';
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TABLE t (i TINYINT);
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO t SET i = 128;
ERROR 1264 (22003): Out of range value adjusted for column 'i' at row 1

mysql> SELECT i FROM t;
Empty set (0.00 sec)

示例 5:在严格模式和ERROR_FOR_DIVISION_BY_ZERO set 下,除以零会导致错误,而不是 NULL.

在非严格模式下,除以零的结果为 NULL

mysql> SET sql_mode='';
Query OK, 0 rows affected (0.01 sec)

mysql> CREATE TABLE t (i TINYINT);
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO t SET i = 1 / 0;
Query OK, 1 row affected (0.00 sec)

mysql> SELECT i FROM t;
+------+
| i    |
+------+
| NULL |
+------+
1 row in set (0.03 sec)

但是,如果正确的 SQL 模式有效,除以零是错误的:

mysql> SET sql_mode='STRICT_ALL_TABLES,ERROR_FOR_DIVISION_BY_ZERO';
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TABLE t (i TINYINT);
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO t SET i = 1 / 0;
ERROR 1365 (22012): Division by 0

mysql> SELECT i FROM t;
Empty set (0.01 sec)

例子 6。精确值文字被评估为精确值。

近似值文字使用浮点数计算,但精确值文字处理为 DECIMAL

mysql> CREATE TABLE t SELECT 2.5 AS a, 25E-1 AS b;
Query OK, 1 row affected (0.01 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> DESCRIBE t;
+-------+-----------------------+------+-----+---------+-------+
| Field | Type                  | Null | Key | Default | Extra |
+-------+-----------------------+------+-----+---------+-------+
| a     | decimal(2,1) unsigned | NO   |     | 0.0     |       |
| b     | double                | NO   |     | 0       |       |
+-------+-----------------------+------+-----+---------+-------+
2 rows in set (0.01 sec)

例 7。如果聚合函数的参数是精确数值类型,则结果也是精确数值类型,其标度至少是参数的标度。

考虑这些陈述:

mysql> CREATE TABLE t (i INT, d DECIMAL, f FLOAT);
mysql> INSERT INTO t VALUES(1,1,1);
mysql> CREATE TABLE y SELECT AVG(i), AVG(d), AVG(f) FROM t;

结果仅为浮点参数的双精度值。对于精确类型参数,结果也是精确类型:

mysql> DESCRIBE y;
+--------+---------------+------+-----+---------+-------+
| Field  | Type          | Null | Key | Default | Extra |
+--------+---------------+------+-----+---------+-------+
| AVG(i) | decimal(14,4) | YES  |     | NULL    |       |
| AVG(d) | decimal(14,4) | YES  |     | NULL    |       |
| AVG(f) | double        | YES  |     | NULL    |       |
+--------+---------------+------+-----+---------+-------+

结果仅为浮点参数的双精度值。对于精确类型参数,结果也是精确类型。