メインコンテンツまでスキップ

浮動小数点型(FLOATとDOUBLE)

概要

Dorisは2つの浮動小数点データタイプを提供します:FLOATDOUBLE。これらはIEEE 754浮動小数点演算標準に従った可変精度数値タイプです。

タイプエイリアスストレージサイズ説明
FLOATFLOAT4, REAL4バイト単精度浮動小数点
DOUBLEFLOAT8, DOUBLE PRECISION8バイト倍精度浮動小数点

値の範囲

FLOAT

DorisはIEEE-754単精度浮動小数点数を使用し、値の範囲は以下の通りです:

  • -∞ (-Infinity)
  • [-3.402E+38, -1.175E-37]
  • 0
  • [1.175E-37, 3.402E+38]
  • +∞ (+Infinity)
  • NaN (Not a Number)

詳細については、C++ float typeWikipedia Single-precision floating-point formatを参照してください。

DOUBLE

DorisはIEEE-754倍精度浮動小数点数を使用し、値の範囲は以下の通りです:

  • -∞ (-Infinity)
  • [-1.79769E+308, -2.225E-307]
  • 0
  • [+2.225E-307, +1.79769E+308]
  • +∞ (+Infinity)
  • NaN (Not a Number)

詳細については、C++ double typeWikipedia Double-precision floating-point formatを参照してください。

特殊値

通常の数値に加えて、浮動小数点タイプはIEEE 754標準に準拠したいくつかの特殊値を持ちます:

  • InfinityまたはInf:正の無限大
  • -Infinityまたは-Inf:負の無限大
  • NaN:非数値

これらの特殊値はCASTによる変換を通じて生成できます:

mysql> select cast('NaN' as double), cast('inf' as double), cast('-Infinity' as double);
+-----------------------+-----------------------+-----------------------------+
| cast('NaN' as double) | cast('inf' as double) | cast('-Infinity' as double) |
+-----------------------+-----------------------+-----------------------------+
| NaN | Infinity | -Infinity |
+-----------------------+-----------------------+-----------------------------+

浮動小数点数には直感的でない性質もあります。2つの異なるゼロ値、+0-0があります。 これらはほとんどのコンテキストで等しいと見なされますが、符号ビットが異なります。

mysql> select cast('+0.0' as double), cast('-0.0' as double);
+------------------------+------------------------+
| cast('+0.0' as double) | cast('-0.0' as double) |
+------------------------+------------------------+
| 0 | -0 |
+------------------------+------------------------+

浮動小数点演算

算術演算

Doris浮動小数点数は、加算、減算、乗算、除算などの一般的な算術演算をサポートしています。

Dorisは浮動小数点数での0による除算を処理する際に、IEEE 754標準に完全には従わないことに注意が重要です。

Dorisはこの点でPostgreSQLの実装に従い、0による除算時に特別な値を生成する代わりにSQL NULLを返します:

ExpressionPostgreSQLIEEE 754Doris
1.0 / 0.0ErrorInfinityNULL
0.0 / 0.0ErrorNaNNULL
-1.0 / 0.0Error-InfinityNULL
'Infinity' / 'Infinity'NaNNaNNaN
1.0 / 'Infinity'0.00.00
'Infinity' - 'Infinity'NaNNaNNaN
'Infinity' - 1.0InfinityInfinityInfinity

比較演算

IEEE標準は、重要な点で一般的な整数比較とは異なる浮動小数点比較を定義しています。例えば、負のゼロと正のゼロは等しいとみなされ、任意のNaN値は他のどの値とも等しくありません(自身を含む)。すべての有限浮動小数点数は+∞より厳密に小さく、-∞より厳密に大きいです。

結果の一貫性と予測可能性を確保するため、DorisはIEE標準とは異なる方法でNaNを処理します。 Dorisでは、NaNは他のすべての値(Infinityを含む)より大きいとみなされ、NaNはNaNと等しくなります。

mysql> select * from sort_float order by d;
+------+-----------+
| id | d |
+------+-----------+
| 5 | -Infinity |
| 2 | -123 |
| 1 | 123 |
| 4 | Infinity |
| 8 | NaN |
| 9 | NaN |
+------+-----------+

mysql> select
cast('Nan' as double) = cast('Nan' as double) ,
cast('Nan' as double) > cast('Inf' as double) ,
cast('Nan' as double) > cast('123456.789' as double);
+-----------------------------------------------+-----------------------------------------------+------------------------------------------------------+
| cast('Nan' as double) = cast('Nan' as double) | cast('Nan' as double) > cast('Inf' as double) | cast('Nan' as double) > cast('123456.789' as double) |
+-----------------------------------------------+-----------------------------------------------+------------------------------------------------------+
| 1 | 1 | 1 |
+-----------------------------------------------+-----------------------------------------------+------------------------------------------------------+

浮動小数点精度の問題

近似値と精度の損失

浮動小数点数は本質的に近似表現です。これは、特定の小数値が浮動小数点数のバイナリ表現では正確に格納できず、代わりに近似値として格納されることを意味します。その結果、格納と取得の過程で小さな差異が発生する場合があります。

例:

mysql> SELECT CAST(1.3 AS FLOAT) - CAST(0.7 AS FLOAT) = CAST(0.6 AS FLOAT);
+--------------------------------------------------------------+
| CAST(1.3 AS FLOAT) - CAST(0.7 AS FLOAT) = CAST(0.6 AS FLOAT) |
+--------------------------------------------------------------+
| 0 |
+--------------------------------------------------------------+

浮動小数点表現エラーのため、これは期待通りに TRUE と評価されない可能性があります。

演算は結合法則に従わない

浮動小数点演算の精度制限により、浮動小数点数の計算特性は理論的な数学演算とは異なります。浮動小数点の加算と乗算は結合法則と分配法則を厳密には満たしません。

これは重要な結果をもたらします:異なる計算順序により、わずかに異なる結果が生成される可能性があります。 DorisはMPPアーキテクチャを使用しており、データ処理の正確な順序を保証できないため、浮動小数点数を含む計算では、同一の入力データであっても、実行ごとにわずかに異なる結果が生成される可能性があります。

集計関数

浮動小数点値に対する集計関数の実行は、特に大規模なデータセットを扱う際にエラーを蓄積する可能性があります。データに極端に大きい値や小さい値が含まれている場合、これらのエラーはさらに増幅される可能性があります。 計算順序が不確定であるため、データに極値が含まれている場合、同じ集計関数を複数回実行すると異なる結果が得られる可能性があります。

Join演算

集計関数と同様に、浮動小数点列でのテーブル結合は推奨されません。浮動小数点数の精度問題により、理論的には等しい2つの値が内部的にわずかに異なる表現を持つ可能性があり、マッチングに失敗する原因となります。

浮動小数点の出力

浮動小数点数が文字列に変換される際、Dorisは以下の精度ルールに従います:

  • 単精度浮動小数点数(FLOAT)は最低7桁の有効数字を保証
  • 倍精度浮動小数点数(DOUBLE)は最低16桁の有効数字を保証 浮動小数点の出力は科学記法を使用する可能性があるため、浮動小数点の文字列表現の長さは必ずしもその有効数字の桁数と等しくないことに注意してください:
mysql> select cast('1234567' as float) , cast('12345678' as float);
+--------------------------+---------------------------+
| cast('1234567' as float) | cast('12345678' as float) |
+--------------------------+---------------------------+
| 1234567 | 1.234568e+07 |
+--------------------------+---------------------------+

ベストプラクティス

  1. 適切なデータ型を選択する: 財務計算や正確な数値が必要なその他のシナリオでは、浮動小数点型ではなくDECIMAL型を使用してください。

  2. 等価比較に注意する: 特にJOIN操作において、2つの浮動小数点値が等しいかどうかを直接比較することは避けてください。

  3. 文字列変換に注意する: 浮動小数点数を文字列に変換してから元に戻すと、追加の精度損失が発生する可能性があります。

  4. プラットフォームの違いを理解する: 異なるデータベースシステムは、特にNaNやInfinityなどの特殊なケースを扱う際に、浮動小数点演算の処理において微妙な違いがある場合があります(ただし、ほとんどのデータベースシステムは広くIEEE標準に従っています)。

  5. 表示用に結果を適切に丸める: 浮動小数点計算結果を表示する際は、ユーザーに対する精度の問題を軽減するために適切な丸めを検討してください。

キーワード

FLOAT、FLOAT4、REAL、DOUBLE、DOUBLE PRECISION、FLOAT8、floating-point