【マンガで感じる】浮動小数点数 ~小数点の位置が変わる小数~ 精度・粒度・誤差を深掘り 【本当の基礎から学ぶゲームプログラミング】


2026/08/17

「浮動小数点数」を、40年以上のゲームプログラミング経験をマンガで可視化。 小数点の位置が変わることで粒度が変わる便利な小数です。 粒度差が大きいと無視される、誤差で計算結果が合わないなど、気をつけるポイントを理由と共に深掘り解説します。

プログラミングブログ記事一覧
[PR]
【マンガで感じる】浮動小数点数 ~小数点の位置が変わる小数~
[PR]
「浮動小数点数」とは:小数点の位置が変わる小数
「浮動小数点数」の本質は「小数点の位置が変わる小数」です。
有効桁数(精度)は型ごとに固定で、小数点の位置が変わることで、その小数が表現する値の粒度が変わります。 便利に使える小数点数ですが、いくつか注意すべき事項があります。
小数点の位置が変わる小数の例
マンガのケースを詳細に解説します。コンピューター内部は 2進数で、有効桁数は実際にはもっと多いですが、マンガは 10進数で、有効桁数3桁です。
まず 1kg(1,000g) を、有効桁数3桁の g で表現すると、 \(1.00 \times 10^{3}\)g です。
そこに初期スパイスの 1.23g を加えると、 \(1.00123 \times 10^{3}\)g ですが、有効桁数は3桁に丸められて、\(1.00 \times 10^{3}\)g になります。 つまり変わりません。
浮動小数点数は、粒度差が大きいと、小さい数は無視される特徴があります。 これが、社長のスパイス分が無かったことにされてしまった正体です。
スパイスのみを計測することで、適切な小数点の位置になり、有効桁数が3桁のまま、\(1.23 \times 10^{0}\)g および、調合後の \(1.89 \times 10^{0}\)g が計測できました。
C++ の浮動小数点数型
型名
バイト数
精度
float 4
単精度
double8
倍精度
float は「単精度浮動小数点数」、double は「倍精度浮動小数点数」です。例えば有効桁数が10進数換算で、
floatが 6桁、doubleが 15桁などの違いがあります。変数定義
C++ における変数定義は、例えば以下のようにプログラミングします。
float f;
f は float 型の変数」であることを定義しています。
コンパイラ(ソースコードを CPU が読める機械語に変換するプログラム)は、変数 f のための領域として、floatに必要なサイズ(通常 4バイト)を確保する機械語コードを出力します。事実上データサイズは固定
C++ の規格上は、
float と double のデータサイズは定められていません。しかし筆者の経験では、事実上
float が 4バイト(32ビット)、doubleが8バイト(64ビット) 固定です。
そのため引き続きこの認識で大丈夫だと思います。主要なプログラミング言語の浮動小数点数型
C++ 以外の主要な言語の浮動小数点数型についても解説します。
この観点においてプログラミング言語は「静的型付け言語」と「動的型付け言語」に分類されます。
静的型付け言語(C#,Java等)
静的型付け言語は、プログラムでデータ型を指定する言語です。
前述の C++ および、C# や Java など、ゲームプログラミングで主流の言語はこちらです。 また浮動小数点数については、これらの言語も
float および double を使用します。動的型付け言語(JavaScript,Python等)
動的型付け言語は、ソースコードではデータ型を指定せず、実行時に自動的に判断して割り当てる言語です。
例えば JavaScript では、変数に数値が代入されると
number型と判断されます。
実体は「倍精度浮動小数点数」です。Python は、整数と小数で異なりますが、除算等を含めて小数を扱う場合の型は「倍精度浮動小数点数」になります。
「単精度浮動小数点数」と「倍精度浮動小数点数」の詳細
現在のアーキテクチャで用いられる浮動小数点数は、この図の形式です。これは IEEE754 という規格で規定されています。 値は
「\((-1)^{符号部} \times (1 + 仮数部) \times 2^{(指数部-バイアス)}\)」
です。 ※IEEE は「アイトリプルイー」とも「アイイーイーイー」とも読みます
なお、例えば全ビット
0 なら値も 0 になるなど、この式以外の仕様もありますが、本エピソードでは省略します。符号部
符号部でプラスかマイナスを表します。0がプラス、1がマイナスです。指数部-バイアス
指数部からバイアスを引いた値が、2の乗数になります。
単精度であればバイアスの値が 127 で、
指数部8ビットで表現される値の両端 0 と 255 は特殊値で除き、-126 から +127 になります。仮数部
2進数の1.xxx の xxx の部分が仮数部です。有効桁数はこの仮数部のサイズで決まります。
ゲームプログラミングにおける「浮動小数点数」
ゲームプログラミングにおいて浮動小数点数は、現在のアーキテクチャでは頻繁に使用するデータ型です。
現在のアーキテクチャにおけるプロのゲームプログラミングでは、原則として
float を用います。double は、パフォーマンスの問題で不必要には使用しません。
double にするだけで短時間で解決できることも少なくありませんが、安易には使用せず、できるだけ float で乗り切ります。ゲーム機の GPU も
float の計算が高速になるように最適化されています。
通常 double の計算は遅いです。精度と粒度を考慮したマップの広さ:±1kmから±2km
後のエピソードで紹介予定の3Dグラフィックスにおける、空間上のオブジェクトの座標は原則
float で保持します。
そのため、その精度と粒度を考慮する必要があります。結論から書きますと、基本的には中心からの座標が ±1km から多くても ±2km 程度で収まる広さに収めるのが良いでしょう。 それで 0.1mm 程度が最小単位になる粒度です。
当たり判定等の演算も必要なので、これくらいが実質的な上限です。
これ以上広大なマップを舞台にしたゲームでは、マップを ±1km四方で区切って動的に合成、キャラクターの座標をそれに合わせて変換するなどの工夫が必要です。 最新の主要なゲームエンジンには、対応する機能が実装されています。
計算誤差を考慮したプログラミング
浮動小数点数は、計算精度の限界があるため、計算誤差が生じます。 そのため、これを考慮したプログラミングが必要です。
具体的には例えば、オブジェクトが目的の座標に到達したかを調べるための条件式としては等号は使わないようにすべきです。
C++
// 不具合の例:計算誤差で一致しない場合がある if ( fNowX == fAimX && fNowY == fAimY ) { // 目的地に到達した処理 }
// 浮動小数点数の計算誤差に対応した例 if ( isFloatEqual(fNowX,fAimX) && isFloatEqual(fNowY,fAimY) ) { // 目的地に到達した処理 }
関数
isFloatEqual の例も参考までに記します。
実際にはその小数が持つ粒度により具体的な値は調整が必要です。
// 参考 constexpr float fEQUAL_MAX = 0.00001f; bool isFloatEqual( const float fA , const float fB ) { float fDiff = fA - fB; return fDiff < fEQUAL_MAX && -fEQUAL_MAX < fDiff; }
粒度差を考慮したプログラミング
浮動小数点数を用いて、小数点の位置が大きく異なる、つまり粒度差が大きい数同士を加算すると、マンガのように無視されて大惨事になる場合があります。
C++
// 無限ループ不具合 for ( float f = 2000000.0f ; f < 2100000.0f ; f += 0.1f ) { // ループ内処理 }
f を 0.1 ずつ増やして、一定数以上になったら終了する「つもりの」ループプログラムです。
C++ では、単精度浮動小数点数の定数は、数値の最後に f を付けて表現しますしかし実際の挙動は、
f は 2097152.0f までは増えますが、そこからはいくら f += 0.1f; しても数値が変わらなくなります。
その結果無限ループに陥ります。筆者も何度かこの不具合を経験しており、しかも気づきづらいので、注意が必要です。
0.1+0.2が0.3では無い理由:2進数の循環小数
計算精度や粒度の問題以前に、例えば
0.1+0.2 は 0.3 にならないという問題があります。
筆者はこれを知った時は衝撃的でした。このような差異の発生理由を詳しく解説します。
誤差が生じるプログラム例(Python)
まずは以下のPythonプログラムをご覧ください。
Python
print( 0.1+0.2 ) print( 0.1+0.2 == 0.3 )
実行すると
0.3 および True と表示されると考えてしまいそうですが、
実際には 0.30000000000000004、False と表示されます。誤差が生じる理由:2進数の循環小数になる
これは、
0.1 および 0.2 が、2進数の循環小数になってしまい、
誤差が発生するためです。循環小数とは、例えば 10進数で \(\frac{1}{3}\) が
0.3333333… と無限に繰り返す小数です。
有効桁数が決まっていると、その数を 3倍しても 1 には戻りません。
例えば小数点以下2桁なら 0.33 になり、その3倍は 0.99です。
それと同様の現象です。実はこの \(\frac{1}{3}\) は、 3進数なら
0.1 と、小数点以下1桁になります。このように、10進数なら少ない桁数で表現できるが、2進数だと割り切れずに無限に続く循環小数になってしまうケースがあり、その場合に人間が認識しづらい誤差が生じます。
誤差が生じない例:0.5+0.25
一方で、2進数でも少ない桁数で表現でき、誤差が生じない数値があります。
例えば、2進数の
0.1 は、10進数の \(1.0 \times 2^{-1}\) すなわち 0.5。
2進数の 0.01 は、10進数の \(1.0 \times 2^{-2}\) すなわち 0.25。これらを加えると 2進数の
0.11 (10進数の 0.75) になり、誤差は生じません。固定小数点数
小数を表現するもうひとつの代表的な手法として、固定小数点数があります。
これは、例えば4バイト(32ビット)のうち、上位2バイト(16ビット)が整数部、下位2バイト(16ビット)が小数部などと、小数点の位置を固定する手法です。 浮動小数点数に比べて精度不足になりがちで、現在のゲーム機における演算では基本的には使用されていません。
ただし、整数演算の延長で計算できるという利点があり、過去にはゲーム機でも固定小数点数型が用いられたことがありました。
また、小数点以下の桁数が固定という特徴を活かして、当ブログでも 円周率の算出等で使用しています。
【コラム】ビリオンダラー・コードに登場した浮動小数点数
Netflix に『ビリオンダラー・コード』という、グーグルアースの誕生に関するドラマがあります。
そのエピソード1に「浮動小数点数」が出てきます。 これ以上はネタバレになるので控えますが、浮動小数点数の特徴を理解した状態で視聴すれば、より楽しめるかもしれません。
[PR]
マンガで感じる!本当の基礎から学ぶゲームプログラミングとは
「マンガで感じる!本当の基礎から学ぶゲームプログラミング」シリーズでは、 主に、ゲーム開発を題材として、プログラミング時に筆者が脳内でイメージするコンピューター内部動作や本質を、マンガにてお伝えします。
プログラミングの本質をマンガで理解
AI時代のプログラミングは、本質理解が重要です。 本質を理解していれば、あとはAIに任せて、自身を持って完成したプログラムに責任が持てるでしょう。
そのため本シリーズでは、コーディングの実例や詳細よりも、「本質をイメージとして感じられること」を最優先としています。 まずマンガで、情報をできる限り絞り、プログラミングの仕組みやコンピューターの内部動作を、物理的に可視化してお届けします。
そして文章の解説で徹底的に深掘りします。
登場人物紹介
マンガで感じる!本当の基礎から学ぶゲームプログラミングシリーズには、主に社長、クリスタル、およびメカたちが登場します。
※実在の人物とは関係ありません社長
本シリーズの偉い人です。マンガでは、指示すなわち「要件定義」を行います。
クリスタル
社長の指示を、メカを活用して解決します。名前は、コンピューター内部で指揮者の役割を果たす「水晶発振器」に由来します。
メカたち
用途に応じて多数存在し、果たす役割がそれぞれ与えられています。クリスタルの指示に従い、ある時はプログラムの変数や関数のように、ある時はデジタル回路の素子や部品のように振る舞います。
「マンガで感じる!本当の基礎から学ぶゲームプログラミング」にかける想い
筆者が本シリーズにかける想いや、 より詳しいコンセプトは「マンガで感じる!本当の基礎から学ぶゲームプログラミング」にて語っています。 そちらもぜひご覧ください。
本エピソードから読み始めた方へ
もしあなたがプログラム初心者で、「マンガで感じる!本当の基礎から学ぶゲームプログラミング」シリーズを本エピソードから読み始めた場合は、 ぜひ最初のエピソード「プログラム」から読むことをご検討ください。
AIを専属の家庭教師にして浮動小数点数を学ぼう
本記事では、小数点の位置が変わることで粒度が変わる「浮動小数点数」について解説しました。 誤差が生じる理由や、粒度差が大きいと無視される理由も深く掘り下げて解説しています。
マンガを読んで興味が湧いた、解説のこのキーワードが気になった、などあれば、AIを専属の家庭教師に見立てて対話してみましょう。 各人の理解度に応じた質疑応答ができて、理解が深まりますので強くオススメします。
皆さまの浮動小数点数、およびプログラミングの本質理解に、少しでもお役に立てれば幸いです。
補足
- 本記事に記載のプログラムソースコードは、悪意のない範囲で自由に使用・改変していただいて問題ありません。ただし、ご自身の判断と責任でお願いします。
- 記事内容の検討および検証・添削に生成AIの Anthropic Claude と Google Gemini を利用しております。
- 記事内の画像の作成に生成AIの Google Gemini を利用しております。
- 数式表現にMathJaxを使用しております。
- ※各社の登録商標または商標について「®」「™」等の表記はしておりません。
カテゴリー:マンガで感じる!本当の基礎から学ぶゲームプログラミング,【プロ指向者向け】データ型編
[PR]

