計算精度を確保する
2025/04/13

本記事では、この記事で円周率を算出するのに用いた、 計算精度を確保する考え方について解説します。
プログラミングブログ記事一覧
なぜ計算精度を確保する必要があるのか

計算精度を確保すると言われても、何が問題なのかピンと来ない方も多いかと思います。 まずは、この図をご覧ください。
これは Python のプログラムを実行した結果です。 多くのプログラミング言語で、同様の結果になります。
printはそのまま表示…のハズがが
この使い方の print() は、カッコの中を数値をそのまま表示します。 1.0 は1.0、1.000000000000001 は 1.000000000000001 と、そのまま表示されました。

内容が変わってる?
しかし、最後は、1.0000000000000001 が 1.0 に表示内容が変わっています。

これが、計算精度不足で、小さすぎる数が切り捨てられてしまった例になります。 数字の有効桁数が大きい場合に、発生する現象です。
[PR]
どうして桁数に限度があるのか
どうして桁数に限度があるのでしょうか。 それは、数値表現のためのメモリー容量が決まっているからです。
どれくらいが限界なのか
少数を表すメモリー容量は、プログラミング言語内で指定することが可能です。
Python や JavaScript、PHP など、主要なプログラミング言語では、その指定がなければ「倍精度浮動小数点数」が用いられます。 その場合15~16桁が、表現できる限界です。
倍精度浮動小数点数とは

倍精度浮動小数点数は、64ビットで表す浮動小数点数です。
プログラミング言語の C++ などでは double 、Python などでは float64 と指定することが可能です。
浮動小数点数とは
浮動小数点数は、小数点の位置が浮動する、つまり位置が変わる少数の表現方法です。 具体的には、例えば、
\(0.375\)
を
\(3.75 \times 10^{-1} \)
と表現します。内部は2進数
前述の例は10進数で表現しましたが、コンピューターの内部は2進数で扱います。 \(0.375_{(10)}\)は、2進数で \(0.011_{(2)}\) です。 この場合の浮動小数点数は、以下の形になります。
\({1.1 \times 10^{-10}}_{(2)} \)
2進数の \(10_{(2)}\) は 10進数の \(2_{(10)}\)ですのでご注意ください。 この式は10進数に書き直すと以下です。
\({1.5 \times 2^{-2}}_{(10)} = {\frac{1.5}{4}}_{(10)}\)
仮数と指数
前述の \(1.1_{(2)}\) のような、べき乗の元となる数値を仮数、\(-10_{(2)}\)のような、べき乗する数値を指数と呼びます。
\( 仮数 \times 10^{指数} \)
仮数部52ビット
この仮数が、倍精度浮動小数点数の場合は52ビットで表されます。ビットとは情報の最小単位で、0か1の値をとります。 52ビットは、それが52個あることになります。
ビット数は、そのまま2進数の桁数です。 つまり倍精度小数点数は、有効な桁数として、2進数で52桁表現できることになります。
2進数の52桁は、10進数の15~16桁に相当します。
単精度浮動小数点数もある
「倍精度」ということは、倍じゃない精度の浮動小数点数があるのか気になるところですが、あります!32ビットで表す浮動小数点数は、単精度浮動小数点数と呼ばれます。 C++ などでは float 、Python などでは float32 と指定します。
単精度浮動小数点数は、倍精度浮動少数点数に比べて省メモリーかつ高速です。 大量のデータが必要な、グラフィックスを扱うシェーダープログラムでは、主にこちらを使用します。
倍精度浮動小数点数より、高い精度の浮動小数点数もありますが、 いずれにしても有効な桁数は10進数で100桁にも届きません。
計算精度を確保するには追加の仕組みが必要
前記の通り、標準で用意されている数値の表現方法を用いて演算すると、表現できる桁数が不足します。 そのため、何らかの追加の仕組みを導入して、計算精度を確保する必要があります。
別途用意されている仕組みを追加すれば良いことが多いですが、 この記事の円周率を算出する際には、自作の固定小数点数を用いました。
固定小数点数とは
固定小数点数は、小数点の位置および、小数点以下の桁数が固定されている数値の表現方法です。
小数点以下の桁数を決めて確保する

固定小数点のイメージは上図です。 小数点以下の桁数を予め決めて、メモリー容量などを確保します。
前記事で実装した方式では、例えば小数点以下100桁の精度で求める場合は、最初に100桁を表現するのに必要な情報量を確保します。
1.0は1.000…になる
つまり例えば \(1.0\) は、最初から小数点以下100桁ぶんを含めて以下となります。

そして、例えばこれを \(3\)で除算した場合には、以下のように、必要な桁数ぶん計算することで、精度を確保します。

あとは式があれば
固定少数点数の仕組みを用いることで、計算精度は確保できました。
あとは、円周率を求めるための「式」が必要です。 次回の記事で、この、円周率を算出する式について、解説します。
まとめ
本記事では、この記事で円周率を算出するのに用いた、 計算精度を確保する考え方について解説しました。
次回は、円周率を整数の四則演算で表す方法について、基本的な考え方、および高速化手法について、解説します。
補足
- 本記事の浮動小数点数の説明は、省略箇所が少なからずあります。正確には Wikipediaなどをご参照ください。
- 画像内のラスタライズ文字フォントにOpen Font LicenseのNoto Sans Monoを使用しております。
- 数式表現にMathJaxを使用しております。/li>
- ※各社の登録商標または商標について「®」「™」等の表記はしておりません。
カテゴリー:プログラミング解説,円周率計算
[PR]