Ответ 1
Проще говоря,
-
digits10
- количество десятичных цифр, гарантированных для сохранения текста → float → text round-trip. -
max_digits10
- количество десятичных цифр, необходимых для обеспечения правильного поплавка → текст → поплавок в оба конца.
Будут исключения для обоих, но эти значения дают минимальную гарантию. Прочтите оригинальное предложение на max_digits10
для ясного примера, слова профессора У. Кахана и дальнейшие подробности. Большинство реализаций на С++ соответствуют IEEE 754 для их типов данных с плавающей точкой. Для IEEE 754 float
, digits10
- 6
и max_digits10
- 9
; для a double
это 15
и 17
. Обратите внимание, что обе эти цифры не следует путать с фактической десятичной точностью чисел с плавающей запятой.
Пример digits10
char const *s1 = "8.589973e9";
char const *s2 = "0.100000001490116119384765625";
float const f1 = strtof(s1, nullptr);
float const f2 = strtof(s2, nullptr);
std::cout << "'" << s1 << "'" << '\t' << std::scientific << f1 << '\n';
std::cout << "'" << s2 << "'" << '\t' << std::fixed << std::setprecision(27) << f2 << '\n';
Печать
'8.589973e9' 8.589974e+009
'0.100000001490116119384765625' 0.100000001490116119384765625
Все цифры до знака 6 th были сохранены, а цифра 7 th не сохранилась для первого номера. Однако все 27 цифр второго сохранились; this является исключением. Однако большинство номеров становятся не более 7 цифр, и все числа будут одинаковыми в пределах 6 цифр.
Таким образом, digits10
дает количество значимых цифр, на которые вы можете рассчитывать в заданном float
, как те же, что и исходное действительное число в его десятичной форме, из которой оно было создано, т.е. цифры, которые сохранились после преобразование в float
.
Пример max_digits10
void f_s_f(float &f, int p) {
std::ostringstream oss;
oss << std::fixed << std::setprecision(p) << f;
f = strtof(oss.str().c_str(), nullptr);
}
float f3 = 3.145900f;
float f4 = std::nextafter(f3, 3.2f);
std::cout << std::hexfloat << std::showbase << f3 << '\t' << f4 << '\n';
f_s_f(f3, std::numeric_limits<float>::max_digits10);
f_s_f(f4, std::numeric_limits<float>::max_digits10);
std::cout << f3 << '\t' << f4 << '\n';
f_s_f(f3, 6);
f_s_f(f4, 6);
std::cout << f3 << '\t' << f4 << '\n';
Печать
0x1.92acdap+1 0x1.92acdcp+1
0x1.92acdap+1 0x1.92acdcp+1
0x1.92acdap+1 0x1.92acdap+1
Здесь два разных float
s, когда они печатаются с цифрами точности max_digits10
, они дают разные строки, и эти строки при чтении вернут исходный float
, из которого они сделаны. При печати с меньшей точностью они дают один и тот же результат из-за округления и, следовательно, при чтении обратно приводят к тому же float
, когда на самом деле они имеют разные значения.
Таким образом, max_digits10
, по крайней мере, требуется для двукратного смещения двух поплавков в их десятичной форме, так что при обратном обращении к двоичному поплавку мы получаем исходные биты снова, а не немного, до или после него из-за ошибки округления.