実践的な浮動小数点の取り扱い
浮動小数点数の誤差は、実務において重大な影響を及ぼすことがあります。特に金融、科学技術、統計処理などの分野では、誤差の蓄積や丸めの影響によって結果が不正確になるリスクがあります。本章では、.NET(C#)および C++ における実践的な浮動小数点数の取り扱いについて解説します。
金額計算
double
やfloat
は2進数ベースの浮動小数点型で近似的に表現されるため、金額計算には不向きです。特に、0.1 や 0.01 のような有限の2進数で表現できない値を扱う場合、誤差の影響が発生しやすくなります。C#では、decimal
型を使用することで、10進数ベースの固定小数点数として保証された精度内での演算が可能です。金融・会計・請求処理といった誤差が許容されない分野では、decimal
を使用することをお勧めします。
C# 実例
decimal price = 0.1m;
decimal quantity = 3;
decimal total = price * quantity;
Console.WriteLine(total == 0.3m); // True
多精度演算を必要とする科学技術計算
科学技術計算や統計処理では、double
の精度では不十分な場合があります。特に、非常に小さい値や大きい値を扱う際には、より高精度な数値型が必要です。C++の場合、boostライブラリのmultiprecision
を使用することで、任意の精度の浮動小数点数を扱うことができます。
C++ 実例(Boost)
#include <iostream>
#include <boost/multiprecision/cpp_dec_float.hpp>
namespace mp = boost::multiprecision;
int main()
{
// 型がサポートする10進数の桁数が100で、数の指数を表す符号付き整数型がboost::int32_t(32bit)の浮動小数点数
mp::cpp_dec_float_100 x = 2.0f;
// 平方根を求める
mp::cpp_dec_float_100 result = mp::sqrt(x);
// 出力桁数を設定して出力
std::cout << std::setprecision(std::numeric_limits<decltype(x)>::digits10 + 1)
<< result;
}
浮動小数点制御ワードの使用
浮動小数点演算の丸めモード、例外処理の挙動はCPUレジスターの浮動小数点制御ワードを通じて制御することができます。ただし、_controlfp_s 関数などを使用して浮動小数点制御ワードを扱う場合は注意が必要です。丸めモードや例外処理の動作を変更するとランタイムやライブラリなどで問題が生じる可能性がありますので、制御が必要な処理の範囲に限定して浮動小数点制御ワードを変更し、不要となったら元の状態に戻すことをお勧めします。