12.20.5 정밀 계산의 예
이 섹션에서는 MySQL 5.6에서 정밀 계산의 쿼리 결과를 나타내는 몇 가지 예를 들어 설명합니다. 이러한 예는 섹션 12.20.3 "식의 처리" 및 섹션 12.20.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이 될 것입니다하지만 10 진수 계산에만 적용되지 않습니다. 부동 소수점 계산은 작은 오류가 발생합니다.
+--------+------------------+ | d | f | +--------+------------------+ | 1.0000 | 0.99999999999991 | +--------+------------------+
예 2. 곱셈은 표준 SQL에 필요한 스케일로 실행됩니다. 즉, 스케일 S1
과 S2
를 가진 두 숫자 X1
과 X2
의 경우, 결과의 스케일은
됩니다. S1
+ S2
mysql> SELECT .01 * .01;
+-----------+
| .01 * .01 |
+-----------+
| 0.0001 |
+-----------+
예 3. 정확한 값 수치에 대한 반올림 동작은 잘 정의되어 있습니다.
둥근 동작 (예를 들어, ROUND()
함수를 사용하여 동작)은 기반이되는 C 라이브러리의 구현에 의존하지 않습니다. 즉, 그 결과는 각 플랫폼에 걸쳐 일관성이 있습니다.
정확한 값 컬럼 (
DECIMAL
과 정수)과 정확한 값 수치에 대한 반올림은 "반올림"규칙이 사용됩니다. 0.5 이상 소수부를 가진다 값은 다음과 같이 0에서 먼 가장 가까운 정수로 반올림됩니다.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
이 설정되어있는 경우는 0으로 나눠서 NULL
의 결과가 아니라 오류가 발생합니다.
비 엄밀 모드에서는 0으로 나눠서 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 모드가 활성화되어있는 경우 0으로 나누기 오류가 발생합니다.
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. 정확한 상수 값은 정확한 값으로 평가됩니다.
MySQL 5.0.3 이전에는 엄격 상수 값과 근사치 리터럴은 모두 배정 밀도 부동 소수점 값으로 평가됩니다.
mysql>SELECT VERSION();
+ ------------ + | VERSION () | + ------------ + | 4.1.18-log | + ------------ + 1 row in set (0.01 sec) 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) 2 rows in set (0.04 sec)
MySQL 5.0.3의 시점에서는 근사치 리터럴은 부동 소수점을 사용하여 평가되지만 엄격 상수 값은 DECIMAL
로 처리됩니다.
mysql>SELECT VERSION();
+-----------------+ | VERSION() | +-----------------+ | 5.1.6-alpha-log | +-----------------+ 1 row in set (0.11 sec) 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;
t;
MySQL 5.0.3 이전에는 인수의 형태에 관계없이 결과가 배정 밀도 값입니다.
mysql> DESCRIBE y;
+--------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+--------------+------+-----+---------+-------+
| AVG(i) | double(17,4) | YES | | NULL | |
| AVG(d) | double(17,4) | YES | | NULL | |
| AVG(f) | double | YES | | NULL | |
+--------+--------------+------+-----+---------+-------+
MySQL 5.0.3의 시점에서는 결과가 Double 값으로되는 것은 부동 소수점 인수의 경우뿐입니다. 정확한 값 형식 인수의 경우, 결과도 엄격 값 형식입니다.
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 | |
+--------+---------------+------+-----+---------+-------+
결과가 Double 값으로되는 것은 부동 소수점 인수의 경우뿐입니다. 정확한 값 형식 인수의 경우, 결과도 엄격 값 형식입니다.