この節では、MySQL 5.1 における高精度計算に対するクエリー結果を示す例を紹介します。
例 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
によって要求されたスケールで実施されます。すなわち、スケール
S1
と S2
を持つ 2 つの数、X1
と
X2
に対して、結果のスケールは
S1
+
S2 です。
mysql> SELECT .01 * .01;
+-----------+ | .01 * .01 | +-----------+ |
0.0001 | +-----------+
例 3。丸め動作はよく定義されています。
丸め動作
(たとえば、ROUND()
関数を使用) は基礎をなしている C
ライブラリのインプリメンテーションから独立していて、それは、結果はプラットホームが変わっても一貫していることを意味します。
正確な値のカラム
(DECIMAL
と整数)
と正確な値の数に対する丸めには、「round
half up」 規則が使われます。5
以上の端数を持つ値は、ここに示すように、ゼロからもっとも近い整数に丸められます。
mysql> SELECT ROUND(2.5), ROUND(-2.5);
+------------+-------------+
| ROUND(2.5) | ROUND(-2.5) | +------------+-------------+ | 3 | -3
| +------------+-------------+
しかしながら、浮動小数点値の丸めには、多くのシステム上で 「round to nearest even」 規則を使用している 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
を設定すると、ゼロによる除算がエラーを引き起こし、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。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.07 sec) Records: 1 Duplicates: 0 Warnings: 0 mysql>DESCRIBE t;
+-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | a | double(3,1) | | | 0.0 | | | b | double | | | 0 | | +-------+-------------+------+-----+---------+-------+ 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;
MySQL 5.0.3 (高精度計算が MySQL の中に導入される以前) での結果:
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 による結果:
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
| | +--------+---------------+------+-----+---------+-------+
結果は、浮動小数点引数に対してだけダブルとなります。正確な型の引数の場合、結果も正確な型のものとなります。