固定小数点数は、小数点の位置をあらかじめ決めて、実際には整数として計算する表現方法です。
浮動小数点数のように桁が動かないため扱いが簡単で、金額やセンサー値などに向いています。
この記事では、仕組みや違い、使いどころ、実装のコツを初心者向けに順番に解説します。
固定小数点数とは?浮動小数点数との違い
固定小数点数の定義
基本の考え方
固定小数点数とは、小数を一定の桁数で表すと決めて、その分だけ整数にスケーリングして扱う方法です。
たとえば小数点以下2桁なら、値に100を掛けて整数として保存し、使う時は100で割って読み替えます。
小数点位置を固定して整数計算に置き換えるのが固定小数点の本質です。
小さな例
価格12.34はスケール100なら内部では1234として保持し、表示するときだけ12.34と解釈します。
内部表現は整数、外側の意味付けで小数に戻すという二層の考え方が基本です。
浮動小数点数との違い
概念の違い
浮動小数点数は指数部と仮数部で広い範囲を表しますが、固定小数点数は指数を持たず小数桁数を固定します。
固定小数点は範囲は限られますが精度が一定、浮動小数点は範囲が広い代わりに場所によって精度が変わります。
比較表
| 観点 | 固定小数点数 | 浮動小数点数 |
|---|---|---|
| 小数桁 | 固定 | 可変 |
| 精度 | 一定で直感的 | 値の大きさで変わる |
| 表現範囲 | 狭いが十分に選べる | 非常に広い |
| 速度 | 整数演算が速い環境で有利 | FPUがあれば高速 |
| 決定性 | 高い | 実行環境差が出る場合あり |
| 金額計算 | 向いている | 端数誤差に注意 |
金額や規定の最小単位が決まっているデータは固定小数点が有利で、桁が大きく変動する科学計算は浮動小数点が有利です。
メリットとデメリット
メリット
固定小数点は、同じ桁で計算するために結果がぶれず、丸めの規則も実装しやすいです。
整数として計算することで環境依存が少なく、処理系差のない再現性を得やすい点が大きな長所です。
デメリット
一方で表現範囲はビット幅とスケールによりすぐに頭打ちになり、大きすぎる値や小さすぎる値に弱いです。
スケールの選定を誤るとすぐオーバーフローや精度不足が起きるのが固定小数点の弱点です。
直感的な例
お金の数え方にそっくり
お金は1円や1セントなど最小単位が決まっているので、その単位で数えれば端数は出ません。
固定小数点は「最小単位で数える」発想そのもので、金額計算に相性が良いのです。
物差しの目盛り
定規の最小目盛りが1mmなら、0.1mmは測れませんが1mm単位なら確実です。
固定小数点も決めた目盛り幅の中で正確に扱う代わりに、それより細かい粒度は丸めが必要になります。
固定小数点数の仕組み
スケーリングで小数を整数化
スケールとは
スケールは「何倍して整数にするか」を表す値です。
10進で小数点以下n桁なら10のn乗、2進でビット小数n桁なら2のn乗を使います。
内部値=実数×スケール、実数=内部値÷スケールという往復が固定小数点の基本式です。
変換の往復
12.34をスケール100で整数化すると1234になり、保存や加算は1234で行い、表示では1234÷100=12.34に戻します。
この往復で小数計算を整数演算に変換できるため、速度と再現性を両立できます。
スケール(小数桁)の決め方
決め方の手順
必要な最小単位をまず決め、その単位で割り切れるスケールを採用します。
金額で2桁必要なら100、温度で0.1度なら10のように選びます。
「どこまでの細かさが本当に必要か」を先に決めるのが失敗しない第一歩です。
例での比較
| 用途 | 最小単位の例 | スケール例 | 補足 |
|---|---|---|---|
| 日本円 | 1円 | 1 | 端数なし |
| 一般的な通貨 | 0.01 | 100 | 2桁小数 |
| 温度 | 0.1度 | 10 | 気象・室内向け |
| 角度 | 0.01度 | 100 | 方位やUI表示 |
| 加速度 g | 0.001g | 1000 | センサーの分解能に合わせる |
スケールは大きすぎても小さすぎても不都合が出るため、実データの範囲と最小単位から逆算してください。
ビット幅と表現範囲
代表的な範囲
ビット幅が決まると、内部整数の最大値と最小値が決まり、スケールで割った値が実用範囲になります。
ビット幅×スケールの組み合わせで表現可能な最大値が一意に決まります。
| 整数型 | 内部整数の範囲(符号あり) | スケール100での実数範囲 |
|---|---|---|
| 16bit | -32768 ~ 32767 | -327.68 ~ 327.67 |
| 32bit | -2147483648 ~ 2147483647 | -21474836.48 ~ 21474836.47 |
| 64bit | -9223372036854775808 ~ 9223372036854775807 | -92233720368547758.08 ~ 92233720368547758.07 |
必要最大値がこの範囲に収まるかを先に確認し、余裕を持って大きめのビット幅を選ぶと安全です。
余裕を持つ理由
丸めや一時的な計算で一瞬大きな値が出ることがあるため、ぎりぎりの範囲は避けます。
乗算や合計の中間値でオーバーフローしないだけの余裕をとることが実務では重要です。
符号あり/なしの違い
選び方の指針
負の値を扱うなら符号あり、有り得ないなら符号なしにして表現範囲を広げます。
温度や差分のように負になり得る量は符号ありが自然です。
データの性質に合わせて符号ありなしを早めに決めて、全体で統一してください。
丸めと切り捨て
主な丸め方式
小数から整数へ、またはスケール変更のときに丸めが必要です。
代表的な方式は切り捨て、切り上げ、四捨五入、銀行丸めです。
どの丸めをいつ使うかを仕様として明文化しておくと結果が安定します。
| 方式 | 説明 | 例 1.234→2桁 | 例 1.235→2桁 |
|---|---|---|---|
| 切り捨て | 常に下方向 | 1.23 | 1.23 |
| 切り上げ | 常に上方向 | 1.24 | 1.24 |
| 四捨五入 | 5以上を繰り上げ | 1.23 | 1.24 |
| 銀行丸め | ちょうど5は偶数に | 1.23 | 1.24 |
金融や集計で偏りを減らしたい場合は銀行丸め、UI表示は四捨五入など使い分けが定番です。
使い分けの目安
内部計算は切り捨てや銀行丸め、ユーザー表示は四捨五入にするなど目的で切り替えます。
丸め規則を混在させると差異が出るため、処理ごとに固定して守ることが大切です。
誤差の出方
量子化誤差
固定小数点では最小単位以下の情報は表せず、丸めで最大0.5単位程度の誤差が出ます。
誤差は常に最小単位を超えないため、許容範囲を事前に見積もれば安心して使えます。
蓄積と対策
繰り返しの計算で丸めが重なると偏りが大きくなる場合があります。
定期的に高精度値で再計算したり、銀行丸めを採用して偏りを抑えると安定します。
誤差が増えやすいのはスケール変更や乗除算の場面で、そこでの丸め戦略が要です。
固定小数点数の使いどころと注意点
金額計算に強い理由
端数と税の処理
通貨は小数桁が決まっているため、固定小数点なら0.1や0.01が正確に表せます。
浮動小数点特有の0.1誤差を避けられるので、税計算や合計でズレません。
金額は固定小数点か10進のDecimal型を使うのが安全です。
税率の丸め位置を仕様で固定することを忘れないでください。
組込み/ゲームでの高速化
速さと決定性
FPUが弱い機器では整数演算が有利で、ゲームの物理やアニメーションも固定小数点で十分な精度を得られます。
同じ入力が同じ結果になる決定性が高く、マルチプラットフォームでの再現性に強いのも利点です。
センサー値や信号処理
実例のスケーリング
温度0.1度単位、加速度0.001g単位など、センサーの分解能に合わせてスケールを決めると処理がシンプルになります。
生の整数をやり取りし、必要なときだけスケールで解釈する設計が堅牢です。
不向きなケース
避けたい場面
天文学的な大きさや極小の値を同時に扱う科学計算、指数関数的に増減するデータは浮動小数点が適しています。
固定小数点はダイナミックレンジが狭く、桁が激しく変動する問題には不向きです。
よくある落とし穴
典型パターンと回避
スケールの違う値をそのまま足す、中間結果でオーバーフローする、乗算後にスケールを戻し忘れる、といったミスが典型です。
全ての値でスケールと単位を明示し、乗算や除算の直後に必ず再スケーリングする習慣をつけてください。
整数の割り算は自動で切り捨てになるため、丸めたい場合は意識的に処理を入れましょう。
プログラミングでの実装方法とコツ
型の選び方
スケールと範囲から逆算
まず最大値と必要な小数桁から内部整数の上限を計算し、それを収められるビット幅を選びます。
迷ったら64bit整数を基準にし、乗算の中間値はさらに広い型を使うと安全です。
早見表
| 想定最大値と小数桁 | 必要な内部最大値の目安 | 推奨整数型 |
|---|---|---|
| 30万まで、2桁 | 300000×100=3e7 | 32bit符号あり |
| 2千万まで、2桁 | 2e7×100=2e9 | 32bit符号ありギリギリ、余裕なら64bit |
| 数千兆まで、2桁 | 1e15×100=1e17 | 64bit符号あり |
| 1e18超、2桁 | 1e20以上 | 128bit相当や多倍長が必要 |
「最大値×スケール」が内部整数で収まるかを常に確認します。
加算/減算のコツ
スケール一致が大前提
同じスケールの値同士なら、そのまま整数を足し引きすれば問題ありません。
スケールが違う値は必ずどちらかに合わせてから計算し、単位の混在をなくします。
桁あふれの見張り
合計や差分で上限に近づくとオーバーフローする可能性があるため、境界値を監視するか大きめの型に切り替えます。
和や累積には一回り大きい型を使うのが実務の定石です。
乗算/除算のコツ
再スケーリングの基本
固定小数点同士を掛けると内部ではスケールが二乗になり、そのままでは大きすぎます。
乗算後は必ずスケールで割り戻して元のスケールに整えます。
丸めを同時に行う
丸めを入れるなら、例えば四捨五入は「(a×b + スケール/2) ÷ スケール」のように計算します。
中間のa×bは一時的に広い整数型で保持し、割り戻す直前に丸めを適用するのがコツです。
広い型を使わないとa×b自体がオーバーフローする危険があります。
比較と四捨五入
比較は整数同士
スケールが同じなら内部整数をそのまま比較します。
違う場合は共通スケールに合わせてから比較します。
小数に直してから比較するより、整数で比較した方が速くて安全です。
指定桁への丸め
表示桁を減らすときは対象のスケールに合わせ、四捨五入なら「加えてから割る」、切り捨てなら「そのまま割る」を徹底します。
丸めの規則を関数化して共通利用すると、実装ブレを防げます。
オーバーフロー対策
事前チェック
計算前に上限を超えそうかをチェックし、超えるならエラーにするか大きい型へ切り替えます。
特に乗算と合計は危険域に入りやすいため、ガードを標準装備にしてください。
飽和と例外
上限で打ち止めにする飽和処理や、例外やエラーを返す方針を決め、全体で統一します。
仕様として「どう壊れるか」を決めておくと、バグが問題へ発展するのを抑えられます。
静かに桁あふれして値が巻き戻るのが最悪の事故です。
言語別のポイント
C/C++
int32_tやint64_tで内部整数を持ち、スケールは定数や型で固定します。
乗算の中間はint64_tや__int128で受けると安心です。
丸めと再スケーリングを関数に切り出し、全ての演算で共通化してください。
C#/.NET
金額はdecimalが便利ですが、決定性や速度目的でlong+スケールを使う設計もあります。
decimalと固定小数点を混用しない設計にし、どちらかへ統一すると混乱を避けられます。
Java
金額はBigDecimalが安全で、スケールや丸めモードを明示できます。
高速化が必要ならlong+スケールも選択肢です。
BigDecimal同士の演算でも丸めモードを常に指定する癖をつけましょう。
Python
decimal.Decimalを使うか、intで固定スケールを運用します。
入力時と表示時のスケール変換を関数で統一し、整数計算部分はなるべく一貫させます。
JavaScript/TypeScript
Numberは倍精度浮動小数点なので金額は誤差に注意が必要です。
BigInt+スケールやdecimalライブラリの利用が現実的です。
入出力でNumberへ戻すときの丸め規則を明示して統一します。
Rust
fixedやrust_decimalなどのクレートがあり、型レベルでスケールを固定できます。
乗算の中間値は幅広い型にキャストし、checkedやsaturatingのAPIを活用してください。
SQLやデータベース
DECIMALやNUMERICは十進固定桁です。
アプリとDBでスケールを揃え、桁数を超える入力の扱いを決めます。
DBの桁設定とアプリのスケールを一致させると不整合がなくなります。
テストと検証
境界値と一致性
最小値、最大値、0、丸め境界(…x.x5)などを中心にテストし、表示やシリアライズで往復して一致するかを確認します。
「変換→計算→逆変換」で値が想定誤差内に収まることを自動テストにします。
ゴールデン値で検証
信頼できる高精度計算(BigDecimalやDecimal)を基準に、固定小数点の結果との差を検証します。
差が最小単位以内であることを合格条件にすれば、安心してリファクタリングできます。
まとめ
固定小数点数は、小数点位置を決めて整数として扱うことで、速さと決定性、そして直感的な精度管理を実現します。
金額やセンサー値など最小単位が明確な場面に強く、丸めや範囲をきちんと設計すれば安定した結果が得られます。
必要な最小単位と最大値からスケールとビット幅を選び、乗除算後の再スケーリングと丸めを徹底することが、固定小数点活用の成功の鍵です。
