Documentation Home
MySQL 8.0 リファレンスマニュアル
Download this Manual
PDF (US Ltr) - 36.1Mb
PDF (A4) - 36.2Mb


このページは機械翻訳したものです。

12.25.5 高精度計算の例

このセクションでは、MySQL での精度の高い数学的クエリー結果を示す例をいくつか示します。 これらの例は、セクション12.25.3「式の処理」およびセクション12.25.4「丸め動作」で説明されている原則を示しています。

例 1 数値は、可能であれば、指定されたとおりにその厳密値で使用されます。

Press CTRL+C to copy
mysql> SELECT (.1 + .2) = .3; +----------------+ | (.1 + .2) = .3 | +----------------+ | 1 | +----------------+

浮動小数点値の場合、結果は不正確です。

Press CTRL+C to copy
mysql> SELECT (.1E0 + .2E0) = .3E0; +----------------------+ | (.1E0 + .2E0) = .3E0 | +----------------------+ | 0 | +----------------------+

厳密値と近似値の処理の違いを確認するための別の方法として、合計値に小さい数値を何回も加える方法があります。 ある変数に .0001 を 1,000 回加える次のストアドプロシージャーを考えてみます。

Press CTRL+C to copy
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;

論理的には、df の両方の合計値が 1 になるはずですが、それは 10 進数の計算にしか当てはまりません。 浮動小数点の計算では、小さなエラーが発生します。

Press CTRL+C to copy
+--------+------------------+ | d | f | +--------+------------------+ | 1.0000 | 0.99999999999991 | +--------+------------------+

例 2 乗算は、標準 SQL に必要なスケールで実行されます。 つまり、スケール S1S2 を持つ 2 つの数値 X1X2 の場合、結果のスケールは S1 + S2 になります。

Press CTRL+C to copy
mysql> SELECT .01 * .01; +-----------+ | .01 * .01 | +-----------+ | 0.0001 | +-----------+

例 3 厳密値数値に対する丸め動作は、適切に定義されています。

丸め動作 (たとえば、ROUND() 関数を使用した動作) は、ベースとなる C ライブラリの実装には依存しません。つまり、その結果は各プラットフォームにわたって一貫性があります。

  • 厳密値カラム (DECIMAL と整数) および厳密値数値に対する丸めでは、四捨五入ルールが使用されます。 小数部が .5 以上の値は、次に示すようにゼロから最も近い整数に丸められます:

    Press CTRL+C to copy
    mysql> SELECT ROUND(2.5), ROUND(-2.5); +------------+-------------+ | ROUND(2.5) | ROUND(-2.5) | +------------+-------------+ | 3 | -3 | +------------+-------------+
  • 浮動小数点値に対する丸めでは、C ライブラリが使用されます。これは、多くのシステムでは偶数丸めルールを使用します。 2 つの整数の間に小数部が完全に半分の値がある場合、最も近い偶数に丸められます:

    Press CTRL+C to copy
    mysql> SELECT ROUND(2.5E0), ROUND(-2.5E0); +--------------+---------------+ | ROUND(2.5E0) | ROUND(-2.5E0) | +--------------+---------------+ | 2 | -2 | +--------------+---------------+

例 4 厳密モードでは、カラムの範囲を外れている値を挿入すると、正当な値への切り捨てではなく、エラーが発生します。

MySQL が厳密モードで実行されていない場合は、正当な値への切り捨てが発生します。

Press CTRL+C to copy
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)

ただし、厳密モードが有効になっている場合は、エラーが発生します。

Press CTRL+C to copy
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 の結果が生成されます。

Press CTRL+C to copy
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 による除算はエラーになります。

Press CTRL+C to copy
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 として処理されます:

Press CTRL+C to copy
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 集約関数への引数が厳密値数値型である場合は、その結果も、少なくとも引数と同じスケールを持つ厳密値数値型になります。

これらのステートメントを考慮してください。

Press CTRL+C to copy
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;

結果が倍精度値になるのは浮動小数点引数の場合だけです。 厳密値型引数の場合は、結果も厳密値型になります。

Press CTRL+C to copy
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 | | +--------+---------------+------+-----+---------+-------+

結果が倍精度値になるのは浮動小数点引数の場合だけです。 厳密値型引数の場合は、結果も厳密値型になります。