3

In writing a function for scientific application, I ran into issues. I traced it back to MySQL's lack of precison.

Here is the page from the official documentation which claims that The maximum number of digits for DECIMAL is 65 - http://dev.mysql.com/doc/refman/5.6/en/fixed-point-types.html . It also describes how the value will be rounded if it exceeds the specified precison.

Here is reproducible code (a mysql stored function) to test it -

  DELIMITER $$
  DROP FUNCTION IF EXISTS test$$
  CREATE FUNCTION test
      (xx DECIMAL(30,25)
      )
      RETURNS DECIMAL(30,25)
      DETERMINISTIC
    BEGIN
      DECLARE result DECIMAL(30,25);
      SET result = 0.339946499848118887e-4;
      RETURN(result);
   END$$
   DELIMITER ;

If you save the code above in a file called test.sql, you can run it by executing the following in mysql prompt -

source test.sql;
select test(0);

It produces the output -

+-----------------------------+
| test(0)                     |
+-----------------------------+
| 0.0000339946499848118900000 |
+-----------------------------+
1 row in set (0.00 sec)

As you can see, the number is getting rounded at the 20th digit, and then five zeroes are being added to it to get to the required/specified precison. That is cheating.

Am I mistaken, or is the documentation wrong?

4

2 に答える 2

3

これは、mysql が を として扱い、 を として扱うために0.339946499848118887e-4発生float0.0000339946499848118887ますfixed point

mysql> select cast(  0.339946499848118887e-4 as DECIMAL(30, 25));
+----------------------------------------------------+
| cast(  0.339946499848118887e-4 as DECIMAL(30, 25)) |
+----------------------------------------------------+
|                        0.0000339946499848118900000 |
+----------------------------------------------------+
1 row in set (0.00 sec)

mysql> select cast(  0.0000339946499848118887 as DECIMAL(30, 25));
+-----------------------------------------------------+
| cast(  0.0000339946499848118887 as DECIMAL(30, 25)) |
+-----------------------------------------------------+
|                         0.0000339946499848118887000 |
+-----------------------------------------------------+
1 row in set (0.00 sec)

精度の数学に関するmysqlのドキュメントで説明されているように- 式の処理-

近似値が存在する場合、式は近似値であり、浮動小数点演算を使用して評価されます。

数値型に関するドキュメントから引用すると、

似ているように見える 2 つの数値は、異なる方法で処理される場合があります。たとえば、2.34 は正確な値 (固定小数点) の数値ですが、2.34E0 は近似値 (浮動小数点) の数値です。

于 2013-09-01T08:10:52.663 に答える
2

私はSQLについて何も知りませんが、私の推測では次の行になるでしょう:

  SET result = 0.339946499848118887e-4;

MySQL が私が知っている他の言語のようなものである場合、これは最初に右辺を評価し、次に値を に割り当てますresult。宣言されている型resultや宣言されている精度に関係なく、評価時に右側がすでに精度を失っていても問題ありません。これはほぼ確実にここで起こっていることです。

結果を再現できますが、その行を次のように変更すると

  SET result = cast('0.339946499848118887e-4' as decimal(30, 25));

(精度が指定されていない浮動小数点定数からではなく、文字列からキャストする)その後、正しく取得します

+-----------------------------+
| test(0)                     |
+-----------------------------+
| 0.0000339946499848118887000 |
+-----------------------------+
1 row in set (0.00 sec)

望んだ通りに。それがあなたの修正です。


ところで、30 を超えることscaleはできないというドキュメントは、セクション12.19.2 にあるようです。DECIMAL データ型の変更:DECIMAL(precision, scale)

DECIMAL 列の宣言構文は DECIMAL(M,D) です。MySQL 5.6 の引数の値の範囲は次のとおりです。

M は最大桁数 (精度) です。範囲は 1 から 65 です (MySQL の古いバージョンでは 1 から 254 の範囲が許可されていました)。

D は、小数点 (スケール) の右側の桁数です。範囲は 0 ~ 30 で、M 以下でなければなりません。

于 2013-09-01T03:34:34.670 に答える