質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.48%

  • MySQL

    6008questions

    MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

  • 浮動小数点

    6questions

    浮動小数点は、コンピュータが数値を扱う際に実数を表現する方法のひとつです。 数値を、それぞれの桁の値が並んでいる仮数部と、小数点の場所を示す指数部で表します。

MySQLの小数点計算の切り捨て(四捨五入)される桁数

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 508

yetis

score 18

1〜3のような計算をした時に、切り捨て(四捨五入)される桁数に関する質問です。

show variables like "div_precision_increment";
-- 4
select version();
-- 5.5.39-log 

以下はそれぞれどういった理由で、それぞれの結果になるのでしょうか?

1. 0.8999 の小数点以下4桁とdiv_precision_increment=4を足して、小数点8桁で四捨五入されている状態でしょうか

select 0.8999 / 30
-- 0.02999667

2. 小数点以下サポートの30桁以下は切り捨てられて四捨五入されている状態でしょうか
(それか30桁に行ったので単に近似値表示がされている?)

select 0.8999999999999999999999999999999999999 / 30
-- 0.030000000000000000000000000000

3. この場合に四捨五入されていない(ように見える)のはなぜでしょうか

select 0.89999 /30
-- 0.029999666

浮動小数点数、MySQLの特性など含めてどのような動きになっているのか
ご教示いただけますと幸いです。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

0

以下、いずれも MySQL のマニュアルを参考にしてください。

マニュアルの記述通りで、除算演算子の場合の有効桁数は、除数・被除数のうちの精度の高い方に、div_precision_increment の桁数を足した物になります。

マニュアルの記述より、DECIMAL 型の最大精度は (65, 30) です。ですので小数点以下30桁を超える場合は31桁目で四捨五入された値を利用します。

mysql> select cast(0.8999999999999999999999999999999 as decimal(65,30));
+-----------------------------------------------------------+
| cast(0.8999999999999999999999999999999 as decimal(65,30)) |
+-----------------------------------------------------------+
|                          0.900000000000000000000000000000 |
+-----------------------------------------------------------+
1 row in set (0.00 sec)

3 0.89999 / 30 が近似値になってしまっているようです。例えば

mysql> select 0.89999/30, 0.89999/30.0, cast(0.89999 as decimal(6,5))/30, cast(0.89999 as decimal(6,5))/30.0;
+-------------+--------------+----------------------------------+------------------------------------+
| 0.89999/30  | 0.89999/30.0 | cast(0.89999 as decimal(6,5))/30 | cast(0.89999 as decimal(6,5))/30.0 |
+-------------+--------------+----------------------------------+------------------------------------+
| 0.029999666 |  0.029999667 |                      0.029999666 |                        0.029999667 |
+-------------+--------------+----------------------------------+------------------------------------+
1 row in set (0.00 sec)


と、除数を 30.0 とすると結果が違うことが分かります。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/23 00:05

    ご丁寧な回答ありがとうございます。
    1なのですが、マニュアルに

    ```
    / を使用して実行される除算では、2 つの正確な値のオペランドを使用したときの結果のスケールが、1 番目のオペランドに div_precision_increment システム変数 (デフォルトでは 4) の値を加えた値になります。たとえば、式 5.05 / 0.014 の結果のスケールは、小数点以下 6 桁になります (360.714286)。
    ```
    1番目のオペランドとなっているので、 `被除数` の精度に +4 ? のように捉えていました。
    ただ `結果の精度が、最大の精度を持つオペランドの精度` とも書いてあるので....???

    試した限りでは `1 番目のオペランド + 4` のようにも思えます。
    ```
    mysql> select 5.05 / 0.0140000000;
    +---------------------+
    | 5.05 / 0.0140000000 |
    +---------------------+
    | 360.714286 |
    +---------------------+
    1 row in set (0.01 sec)

    mysql> select 5.050000 / 0.014;
    +------------------+
    | 5.050000 / 0.014 |
    +------------------+
    | 360.7142857143 |
    +------------------+
    1 row in set (0.00 sec)
    ```

    難しいですね...

    キャンセル

  • 2018/06/23 17:38

    > `被除数` の精度に +4
    私にもそう読めます。
    > `結果の精度が、最大の精度を持つオペランドの精度`
    それは「オペランドのいずれかが実数値または文字列値である場合」なので今回無関係でしょう。

    3番について、厳密値と近似値の違いというのはありそうなことではありますが、
    残る疑問は、なぜ1番と同じ書き方なのに厳密値か近似値かが変わるのか(マニュアルを見た限り厳密値と扱われそう)と、
    近似値になったからといって切り捨てになる理由が分からないことですね。
    https://dev.mysql.com/doc/refman/5.6/ja/precision-math-rounding.html
    DECIMAL または整数カラムへの挿入の場合では四捨五入になるという記述はあり、selectで直接出力したときどういう扱いになるかは分かりませんが、切り捨てというのはあまり一般的でないので不思議です。

    キャンセル

-1

小数点以下何桁で切り捨て、といいますが、あくまで表示するために、表示上の都合で切り捨てている、ということなだけで、内部的には保持している変数の精度で保持してます。

小数点以下4桁までしか表示していないので、内部の変数は小数点以下4桁でなんかしている、というのは間違いです。

#逆に、精度いっぱい小数点以下14桁とか出されても困るでしょw

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/22 23:56

    > 内部の変数は小数点以下4桁でなんかしている、というのは間違いです。
    なるほど、そうですよね。ありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.48%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • MySQL

    6008questions

    MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

  • 浮動小数点

    6questions

    浮動小数点は、コンピュータが数値を扱う際に実数を表現する方法のひとつです。 数値を、それぞれの桁の値が並んでいる仮数部と、小数点の場所を示す指数部で表します。