私が読んだところによると、double データ型の値の精度は、おおよそ 15 桁の小数点以下です。ただし、1.0/7.0 のように、小数点以下が繰り返される数値を使用すると、変数には 0.14285714285714285 という値 (17 桁) が保持されていることがわかります (デバッガー経由)。
なぜ内部的に 17 桁で表現されるのか、また精度 15 が常に ~15 と記述されるのはなぜなのかを知りたいです。
ベストアンサー1
DBL_MANT_DIG
IEEE double には 53 の有効ビットがあります (のの値です<cfloat>
)。これは約 15.95 の 10 進数桁数 (log10(2 53 )) です。実装ではDBL_DIG
切り捨てが必要なため、16 ではなく 15 に設定されます。そのため、精度の 10 進数桁数がほぼ 1 つ増えます ( で示されるものを超えてDBL_DIG==15
)。
このnextafter()
関数は、指定された数値に最も近い表現可能な数値を計算します。指定された数値がどれだけ正確であるかを示すために使用できます。
このプログラム:
#include <cstdio>
#include <cfloat>
#include <cmath>
int main() {
double x = 1.0/7.0;
printf("FLT_RADIX = %d\n", FLT_RADIX);
printf("DBL_DIG = %d\n", DBL_DIG);
printf("DBL_MANT_DIG = %d\n", DBL_MANT_DIG);
printf("%.17g\n%.17g\n%.17g\n", nextafter(x, 0.0), x, nextafter(x, 1.0));
}
私のシステムでは次の出力が得られます:
FLT_RADIX = 2
DBL_DIG = 15
DBL_MANT_DIG = 53
0.14285714285714282
0.14285714285714285
0.14285714285714288
(%.17g
たとえば、 を に置き換えると、%.64g
意味のない数字をさらに表示できます。)
ご覧のとおり、最後の小数点の数字は、連続する値ごとに3ずつ変化します。1.0/7.0
(5
)の最後の数字が数学的な値と一致するのは、ほとんど偶然であり、幸運な推測です。そして、正しい数字は丸みを帯びたdigit は であり6
、 ではありません5
。1.0/7.0
を に置き換えると1.0/3.0
、出力は次のようになります。
FLT_RADIX = 2
DBL_DIG = 15
DBL_MANT_DIG = 53
0.33333333333333326
0.33333333333333331
0.33333333333333337
予想どおり、10 進数で約 16 桁の精度が表示されます。