浮動小数点型(FLOAT と DOUBLE)
概要
Doris は、FLOAT と DOUBLE の二種類の浮動小数点データ型を提供します。これらは、浮動小数点演算に関する IEEE 754 規格に従う可変精度の数値型です。
| 型 | 別名 | 保存サイズ | 説明 |
|---|---|---|---|
| FLOAT | FLOAT4, REAL | 4 バイト | 単精度浮動小数点数 |
| DOUBLE | FLOAT8, DOUBLE PRECISION | 8 バイト | 倍精度浮動小数点数 |
値の範囲
FLOAT
Doris は IEEE 754 の単精度浮動小数点数を使用し、その値の範囲は次のとおりです。
- -∞ (-Infinity)
- [-3.402E+38, -1.175E-37]
- 0
- [1.175E-37, 3.402E+38]
- +∞ (+Infinity)
- NaN(非数)
詳細は、C++ の float 型とWikipedia の単精度浮動小数点数形式を参照してください。
DOUBLE
Doris は IEEE 754 の倍精度浮動小数点数を使用し、その値の範囲は次のとおりです。
- -∞ (-Infinity)
- [-1.79769E+308, -2.225E-307]
- 0
- [+2.225E-307, +1.79769E+308]
- +∞ (+Infinity)
- NaN(非数)
詳細は、C++ の double 型とWikipedia の倍精度浮動小数点数形式を参照してください。
特殊な値
通常の数値に加えて、浮動小数点型には IEEE 754 規格に準拠した特殊な値がいくつかあります。
InfinityまたはInf:正の無限大-Infinityまたは-Inf:負の無限大NaN:非数(Not a Number)
これらの特殊な値は、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 |
+-----------------------+-----------------------+-----------------------------+
浮動小数点数には、直感に反する性質もあります。+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 の浮動小数点数は、加算、減算、乗算、除算などの一般的な算術演算に対応しています。
浮動小数点数を 0 で除算する場合、Doris は IEEE 754 規格に完全には従わないことに注意してください。
この点では Doris は PostgreSQL の実装に従い、0 で除算すると特殊な値を生成する代わりに SQL NULL を返します。
| 式 | PostgreSQL | IEEE 754 | Doris |
|---|---|---|---|
| 1.0 / 0.0 | エラー | Infinity | NULL |
| 0.0 / 0.0 | エラー | NaN | NULL |
| -1.0 / 0.0 | エラー | -Infinity | NULL |
| 'Infinity' / 'Infinity' | NaN | NaN | NaN |
| 1.0 / 'Infinity' | 0.0 | 0.0 | 0 |
| 'Infinity' - 'Infinity' | NaN | NaN | NaN |
| 'Infinity' - 1.0 | Infinity | Infinity | Infinity |
比較演算
IEEE 規格では、浮動小数点数の比較が通常の整数の比較と重要な点で異なります。たとえば、負のゼロと正のゼロは等しいとみなされ、NaN はほかのどの値とも等しくありません(NaN 自身も含みます)。有限の浮動小数点数はすべて +∞ より小さく、-∞ より大きくなります。
結果の一貫性と予測可能性を確保するため、Doris は NaN を IEEE 規格とは異なる方法で扱います。 Doris では、NaN はほかのすべての値(Infinity を含む)より大きいとみなされ、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 演算
集約関数と同様に、浮動小数点数の列を使ったテーブルの JOIN は推奨されません。浮動小数点数の精度の問題により、理論上は等しい二つの値でも内部表現がわずかに異なり、結合が成立しない場合があります。
浮動小数点数の出力
4.1.4 以降、浮動小数点数を文字列に変換すると、Doris は値を損失なく往復変換できる最短の文字列を出力します。その文字列を再び FLOAT / DOUBLE として解析すると、元の値と完全に同じ二進値が得られ、余分な桁は出力されません。
出力形式の規則:
- 十進指数が
[-4, 16)の範囲にある場合は、固定小数点表記を使用します。 - それ以外の場合は、小文字の
e、明示的な符号、二桁以上の指数部を使う科学的記数法を使用します。例:1.23456e-05。 - 正のゼロと負のゼロは、それぞれ
0と-0として区別して出力します。 NaN、Infinity、-Infinityの表記は従来どおりです。
mysql> select cast('0.000123456' as double), cast('0.0000123456' as double);
+-------------------------------+--------------------------------+
| cast('0.000123456' as double) | cast('0.0000123456' as double) |
+-------------------------------+--------------------------------+
| 0.000123456 | 1.23456e-05 |
+-------------------------------+--------------------------------+
4.1.4 より前のバージョンでは、有効数字を固定の桁数(FLOAT は約 7 桁、DOUBLE は約 16 桁)で出力していたため、出力された文字列を解析しても元の値に戻らないことがありました。最短の往復変換可能な表現に切り替えた後も、保存される値は変わりません。変わる可能性があるのはテキスト表現だけです。例:
| 4.1.4 より前 | 4.1.4 以降 |
|---|---|
246.9120025634766 | 246.91200256347656 |
15241.38425247656 | 15241.384252476564 |
11.11107561317707 | 11.111075613177073 |
DOUBLE 値 2.0 が一部のテキスト出力で 2.0 と表示される | 2 と表示される |
0.0000123456 | 1.23456e-05 |
この変更は、MySQL プロトコルのクエリ結果、CAST(... AS STRING)、ARRAY / MAP / STRUCT の要素の表示、JSON / VARIANT の表示、SELECT INTO OUTFILE の CSV / Parquet / ORC テキスト出力、EXPORT、Stream Load の戻り値、外部テーブル(Hive / Iceberg / Paimon / JDBC / ES / TVF)の浮動小数点列など、広範囲の出力経路に影響します。
後続のシステムが浮動小数点数の文字列表現を完全一致で照合している場合(たとえば、エクスポートしたファイルを比較する場合)、アップグレード後にそれに合わせて調整してください。
ベストプラクティス
-
適切なデータ型を選ぶ:金銭計算など、正確な数値が必要な場合は、浮動小数点型ではなく
DECIMAL型を使用してください。 -
等価比較に注意する:特に JOIN 演算では、二つの浮動小数点値が等しいかどうかを直接比較することは避けてください。
-
文字列変換に注意する:浮動小数点数を文字列に変換し、再び浮動小数点数に戻すと、精度がさらに失われる可能性があります。
-
プラットフォーム間の違いを理解する:データベースシステムによっては、浮動小数点演算の扱いに細かな違いがあります。特に NaN や Infinity などの特殊な値を扱う場合に注意してください(ただし、ほとんどのデータベースシステムはおおむね IEEE 規格に従います)。
-
表示用の結果を適切に丸める:浮動小数点数の計算結果を表示する場合は、ユーザーに見える精度上の問題を抑えるため、適切な丸めを検討してください。
キーワード
FLOAT, FLOAT4, REAL, DOUBLE, DOUBLE PRECISION, FLOAT8, 浮動小数点