数値型

はじめに

数値型 は、最も使うデータ型と行っても過言ではありません。まずは公式ドキュメントを読み漁りましょう。

数値型とは

その名前の通り、数値を保存できる型です。有理数の一部、整数とほんの少しの小数を扱うことができます。 代数演算が可能で、大小一致の比較もできます。 具体的な型は INT64(INTEGER)、FLOAT64(FLOAT)、NUMERIC の 3 つです。

名前説明ストレージ サイズ
INT64整数型8 バイト
NUMERIC数値型16 バイト
FLOAT64浮動小数点型8 バイト

整数型 INT64

整数は小数部分を持たない数値です。 BigQuery 上では、小数点を打たずに数値を入力すると INT64 型になります。 値域外であったとしても、自動で FLOAT64 や NUMERIC 型になったりはしません。

数値型 NUMERIC

10 進 38 桁の精度と 10 進 9 桁の尺度の正確な数値です。精度は、数値に含まれる桁数です。尺度は、小数点以下の桁数です。 この型は、小数部分を正確に表すことができ、財務計算に適しています。 BigQuery で定義する際には、NUMERIC "123.45" など、STRING の前に NUMERIC と入力します。 または、CAST("123.45" AS NUMERIC) でも同様の結果が得られます。

浮動小数点型 FLOAT64

浮動小数点の値は小数部分のある近似値です。 また、NaN と +/-inf という特別な非数値があります。

BigQuery の算術演算子は、出力が非定形の場合、オーバーフロー エラーが返されます。 また、入力に非定形が含まれる場合、出力が非定形になる算術演算子がほとんどです。

BigQuery では数値に小数点を打つと、FLOAT64 型になります。値域外であったとしても、自動で NUMERIC 型になったりはしません。 また、INT64 型に CAST すると偶数への丸めを行います。端数が 0.5 より小さいなら切り捨て、端数が 0.5 より大きいならは切り上げます。端数がちょうど 0.5 なら切り捨てと切り上げのうち結果が偶数となる方へ丸めます。 INT64 に丸める方向を決めておきたい場合、キャストの前に丸める関数を通しておきましょう。

NUMERIC の不思議

NUMERIC とは何者だろう

INT64 の用途はわかります。数を数えたり、番号をつけたりに使います。 FLOAT64 は小数計算のときに使いますね。INT64 同士の比を出したり、スケールを合わせて比較する時によく出てきます。 FLOAT64 の仕様となる IEEE 754 は CPU の word size に合わせることで、効率の良い命令を使って計算ができます。 これだけで大抵の用途はこなせますが、NUMERIC はどんな時に使うでしょうか。 答えは、「多少遅くてもいいから精度保証付の演算」が必要な時です。

FLOAT64 の不思議

SELECT 0.1 + 0.2 を実行してみましょう。

f0_
10.30000000000000004

が返ってきますね。FLOAT64 は内部表現が 2 進数なので、それで表現できない誤差が積み上がっていくのです。 同じスケールの加減算なら比較的良いですが、乗除算やスケールが全く異なる加減算はこの誤差をとても大きくします。 大小正しくつくことが重要で、その小数第 n 位に着目するケースは多くないため、精度より速度が重要視される環境では FLOAT64 をよく使うでしょう。

NUMERIC の精度

SELECT NUMERIC "0.1" + NUMERIC "0.2" を実行してみましょう。

f0_
10.3

と厳密に正しい結果が返ってきました。10 進 38 桁の精度と 10 進 9 桁の尺度を保証してくれるのです。 オーバーフローでエラーを返してくるのは、FLOAT64 と一緒ですが、自動で丸める処理は一切しません。 丸めが必要なタイミングで人間が指定して丸める必要があります。 しかしこれによって、誤差を積み上げなくてすみます。

消費税 8 %のセブン方式 100 円 * 3 個 = 301 円

消費税 8 %のセブンは税抜き価格を足していってから、最後に消費税をかける方式で話題になりましたね。 税抜 93 円、税込 100 円の物を買ってみましょう。 (93 円 + 93 円 + 93 円) * 1.08 = ROUND(301.32 円) で、小数点以下を四捨五入して 301 円になります。

有効桁数を残すため、なるべく後で掛け算と丸めを行うのは当然でしょう。 しかし、3 回買い物するとどうでしょうか。 (93 円 1.08) + (93 円 1.08) + (93 円 * 1.08) = ROUND(100.44) + ROUND(100.44) + ROUND(100.44) です。 四捨五入して、300 円になります。購入方法によって、支払金額が増えるのです。

これが一般消費者の誤差の積み上げです。暗黙のうちに丸められると困るのです。 もっと大きな額を扱う業界でこれをやられたら、誤差だけでぽんぽん家が立ちます。

NUMERIC の用途

ここまででお分かりでしょう。NUMERIC は精度保証したい時に使います。 数の大小がざっくり分かれば精度の保証がなくても良い、速度の方が重要といった用途なら、FLOAT64 を利用すべきです。 しかしながら、BigQuery 上の四則演算であれば、速度に倍も差があるわけではないです。 数学関数も、NUMERIC と FLOAT64 で利用できる関数に差があるわけでもありません。 気になる点は保存、参照コストが倍になること、FLOAT64 が紛れ込んでもよしなに計算してしまうので、精度劣化に気づけないことですね。

一円を笑う者は一円に泣く

お金を扱う時に FLOAT64 を使うと泣きをみます。 扱っている数字の単位を考えることで、どの精度の型を使えば良いのか検討を進めることができそうです。

まとめ

BigQuery には、INT64、NUMERIC、FLOAT64 の 3 つの数値型があります。 用途によって適切に選ぶことで、正しく意思決定に使えるデータ分析ができるようになります。 それぞれのデータ型を吟味し、ユースケースにあったデータ型でデータ活用を進めたいものです。

Last updated on