int vs float:数値の格納方法
int(整数)と float(浮動小数点数)はプログラミング言語が数値を表現する 2 つの方法で、選び方は実データに触れた瞬間に結果が出ます。
int は正確で数え上げができます。42 は 42 で、丸めも意外もありません。float は近似で連続的です。IEEE 754 倍精度では 0.1 + 0.2 が 0.30000000000000004 になります。初めて会う人は誰でも驚きます。
正確な値域
int は有限です。多くの現代システムで int32 は 2^32 個の異なる値を保持します(−2,147,483,648 〜 2,147,483,647)。int64 は 2^64 個。それを超えると、型はその数値を表現できません。
float はほぼ連続です。IEEE 754 float64(C 系言語の “double”)は約 10^−308 から 10^308 まで表現でき、有効桁は 15〜17 桁。落とし穴:その範囲でも正確には表現できない数値があります。多くの値(0.1 など)は丸められます。
なぜ 0.1 + 0.2 ≠ 0.3 か
2 進浮動小数では 0.1 はきれいな分数ではありません。十進の 1/3 が 0.3333… となるように、2 進の 1/10 は 0.000110011001100… と循環します。float は有限ビットに丸める必要があり、実際に格納される値はわずかにずれます。
2 つの丸めた数値を足すと丸め誤差が累積します。0.1 + 0.2 は 0.3 をわずかに超え、float は 0.30000000000000004 と表示します。
これはバグではなく、IEEE 754 が正しく動いています。バグは、本来正確にすべきところで float を使っていることです。
どちらを使うか
int を使う場面:
- 数えるもの(行、インデックス、サイズ)
- 通貨を最小単位で保存(セント、pence、satoshi — 常に最小整数単位)
- ID、秒/ミリ秒のタイムスタンプ、バイト数
- 正確な等価性が必要(
a == bが期待通り)
float を使う場面:
- 物理量計算(距離、重さ、角度)
- 厳密性より値域が重要な集計
- 広い値域が活きる計算(科学計算、グラフィックス)
- 許容誤差つきの比較を受け入れる(
abs(a - b) < epsilon)
混同の落とし穴
最も微妙なバグは int と float の混同から生まれます。動的型付け言語では:
5 / 2— 多くの言語で整数除算で 2。JavaScript では 2.55.0 / 2— どの言語でも 2.5int(2.5)とMath.floor(2.5)— 多くの言語で 2。JavaScript には int 型がないので挙動が違う
int64 を超える整数(非常に大きな ID、高精度タイムスタンプ、ブロックチェーンの金額)は特別な型が必要です。Python の int は任意精度。C++ は __int128 や boost::multiprecision。JavaScript の数値は常に float64(2^53 を超える整数は BigInt)。
通貨と古典的な教訓
コンピューティング 50 年の歴史で、ほとんどの金融バグは通貨を float で保存したことから生まれました。普遍的な修正:通貨を最小整数単位で保存(セント、ペンス、サトシ)。1999 セントは 19.99 ドルで、絶対に近似しない。人が読む形への変換は表示時にだけ行い、10 進演算を行うライブラリ(または明示的な丸め規則を使った整数除算)を使う。
ツール
JSON や CSV データに埋め込まれた数値を扱う際 — float に見える int や int に見える float に遭遇するかもしれません — JSON to CSV と JSON to YAML は型を変えずに値を忠実に往復します。
SQL では、int か float かの列選択が下流のすべての問い合わせに影響します。SQL Formatter で状況が見えてきます。
関連
- JSON Schema Generator — 明示的な
integerとnumber型が欲しいとき - Regex Tester — 文字列から数値を取り出すため