AOYAMA KOJI's PROGRAMMING BLOG

計算精度を確保する

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

 本記事では、この記事で円周率を算出するのに用いた、 計算精度を確保する考え方について解説します。


なぜ計算精度を確保する必要があるのか


計算精度を確保する fig.2
 計算精度を確保すると言われても、何が問題なのかピンと来ない方も多いかと思います。 まずは、この図をご覧ください。
 これは Python のプログラムを実行した結果です。 多くのプログラミング言語で、同様の結果になります。

printはそのまま表示…のハズがが


 この使い方の print() は、カッコの中を数値そのまま表示します。 1.0 は1.0、1.000000000000001 は 1.000000000000001 と、そのまま表示されました。
計算精度を確保する fig.3

内容が変わってる?


 しかし、最後は、1.0000000000000001 が 1.0 に表示内容が変わっています。
計算精度を確保する
 これが、計算精度不足で、小さすぎる数が切り捨てられてしまった例になります。 数字の有効桁数が大きい場合に、発生する現象です。
[PR]

どうして桁数に限度があるのか


 どうして桁数に限度があるのでしょうか。 それは、数値表現のためのメモリー容量が決まっているからです。

どれくらいが限界なのか


 少数を表すメモリー容量は、プログラミング言語内で指定することが可能です。
 Python や JavaScript、PHP など、主要なプログラミング言語では、その指定がなければ「倍精度浮動小数点数」が用いられます。 その場合15~16桁が、表現できる限界です。

倍精度浮動小数点数とは


計算精度を確保する fig.4
 倍精度浮動小数点数は、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ビット


計算精度を確保する fig.5  この仮数が、倍精度浮動小数点数の場合は52ビットで表されます。
 ビットとは情報の最小単位で、0か1の値をとります。 52ビットは、それが52個あることになります。
 ビット数は、そのまま2進数の桁数です。 つまり倍精度小数点数は、有効な桁数として、2進数で52桁表現できることになります。
 2進数の52桁は、10進数の15~16桁に相当します。

単精度浮動小数点数もある


計算精度を確保する fig.6  「倍精度」ということは、倍じゃない精度の浮動小数点数があるのか気になるところですが、あります!
 32ビットで表す浮動小数点数は、単精度浮動小数点数と呼ばれます。 C++ などでは float 、Python などでは float32 と指定します。
 単精度浮動小数点数は、倍精度浮動少数点数に比べて省メモリーかつ高速です。 大量のデータが必要な、グラフィックスを扱うシェーダープログラムでは、主にこちらを使用します。
 倍精度浮動小数点数より、高い精度の浮動小数点数もありますが、 いずれにしても有効な桁数は10進数で100桁にも届きません。

計算精度を確保するには追加の仕組みが必要


 上記の通り、標準で用意されている数値の表現方法を用いて演算すると、表現できる桁数が不足します。 そのため、何らかの追加の仕組みを導入して、計算精度を確保する必要があります。
 別途用意されている仕組みを追加すれば良いことが多いですが、 この記事の円周率を算出する際には、自作の固定小数点数を用いました。

固定小数点数とは


 固定小数点数は、小数点の位置および、小数点以下の桁数が固定されている数値の表現方法です。

小数点以下の桁数を決めて確保する


計算精度を確保する fig.7
 固定小数点のイメージは上図です。 小数点以下の桁数を予め決めて、メモリー容量などを確保します。
 前記事で実装した方式では、例えば小数点以下100桁の精度で求める場合は、最初に100桁を表現するのに必要な情報量を確保します。

1.0は1.000…になる


 つまり例えば \(1.0\) は、最初から小数点以下100桁ぶんを含めて以下となります。
計算精度を確保する fig.8
 そして、例えばこれを \(3\)で除算した場合には、以下のように、必要な桁数ぶん計算することで、精度を確保します。
計算精度を確保する fig.9

あとは式があれば


 固定少数点数の仕組みを用いることで、計算精度は確保できました。
 あとは、円周率を求めるための「式」が必要です。 次回の記事で、この、円周率を算出する式について、解説します。

まとめ


 本記事では、この記事で円周率を算出するのに用いた、 計算精度を確保する考え方について解説しました。
 次回は、円周率を整数の四則演算で表す方法について、基本的な考え方、および高速化手法について、解説します。

補足


・本記事の浮動小数点数の説明は、省略箇所が少なからずあります。正確には Wikipediaなどをご参照ください。
・画像内のラスタライズ文字フォントにOpen Font LicenseNoto Sans Monoを使用しております。
・数式表現にMathJaxを使用しております。助かります!

カテゴリー:プログラミング解説,円周率計算
[PR]