[前][次][番号順一覧][スレッド一覧]

mysql:6685

From: "matsuda" <"matsuda" <matsuda@xxxxxxxxxx>>
Date: Tue, 10 Dec 2002 20:54:52 +0900
Subject: [mysql 06685] 小数点を含んだ数値の演算について

こんにちわ。
いつもお世話になっております。

環境:Windows2000 SP1
MySQL:4.0.4-beta-max
ローカルでテストしています。

数値a,bを乗算した結果をTRUNCATE関数により小数点以下を
切り捨てた値にしたいのですが、a,bがある数値のときに
結果に誤差が生じてしまいます。

<MySQL実行内容>
-------------------------------------------------
mysql> create table test2
    -> ( suryo numeric(14,4) null,
    ->   tanka numeric(15,3) null,
    ->   kingaku numeric(15,3) null);
Query OK, 0 rows affected (0.74 sec)

mysql> insert into test2 values(2.34,13000,0);
Query OK, 1 rows affected (0.01 sec)

mysql> update test2 set kingaku=truncate(suryo*tanka,0);
Query OK, 1 rows affected (0.00 sec)
Row matched: 1  Changed: 1  Warnings:  0

mysql> select * from test2;
+--------+-----------+-----------+
| suryo  | tanka     | kingaku   |
+--------+-----------+-----------+
| 2.3400 | 13000.000 | 30419.000 |
+--------+-----------+-----------+
1 row in set (0.00 sec)

-------------------------------------------------

本来、2.34*13000=30420となるはずなのですが・・・。
フィールドの型に問題があるのかと思い、
直接以下のようなコマンドを入力してチェックしてみました。

-------------------------------------------------
mysql> select truncate(2.34*13000,0);
+------------------------+
| truncate(2.34*13000,0) |
+------------------------+
|                  30419 |
+------------------------+
1 row in set (0.00 sec)

mysql> select 2.34*13000;
+------------+
| 2.34*13000 |
+------------+
|      30420 |
+------------+
1 row in set (0.00 sec)
-------------------------------------------------

と、上記のような結果になってしまいます。

あるテーブル[table_A]に、上記のテーブル[test2]と同じ構造の
フィールド"suryo"、"tanka"、"kingaku"があり、
"suryo"、"tanka"には各々複数レコードが入っています。
SQL文で

update table_A set kingaku=truncate(suryo*tanka,0);

と実行した後に、"kingaku"フィールドの合計(sum)を算出してみると、
予想の値と違っていたために、1レコードずつチェックしてみたところ、
上記のような数値の組み合わせの時に誤差が生じていることが分かりました。
他にも

truncate(1.17*13500,0) ---> 15794
1.17*13500             ---> 15795

という演算結果がありました。

マニュアルに
==============================================================
コンピュータでは小数点数は正確な数値としては格納されず、double値
として格納されます。
次の結果によってだまされるでしょう
TRUNCATE(10.28*100,0) → 1027
上記は10.28は実際には、10.279999999999999のようなものとして
格納されるために発生します。
==============================================================
と記述されているので、TRUNCATE関数を用いることによって小数点以下が
切り捨てられてしまっていると思われるのですが、こういう場合に
正確な結果を得たいときには、どうやって回避したら良いのでしょうか?

たまたまこのような数値の組み合わせで得られた結果だと思うのですが、
乗算以外や、上記数値以外にもこういった現象が起こりうると考えると
演算を使用するときには必ず注意した方がいい、
ということになるのでしょうか?

以上、よろしくお願いいたします。

*************
 まつだ









[前][次][番号順一覧][スレッド一覧]

->    6685 2002-12-10 20:54 ["matsuda" <matsuda@x] 小数点を含んだ数値の演算について        
      6687 2002-12-10 22:19 ┣[とみたまさひろ <tomm]                                       
      6695 2002-12-11 12:08 ┃┗[SUGAWARA Hajime <sug]                                     
      6697 2002-12-11 13:15 ┃ ┗[SUGAWARA Hajime <sug]                                   
      6693 2002-12-11 12:02 ┗[madara <madara@xxxxx]