Я запутался в том, что max_digits10
представляет собой. В соответствии с его документация, это 0 для всех целочисленных типов. Формула для типов с плавающей точкой для max_digits10
выглядит как int
«s digits10
«S.
Проще говоря,
digits10
это количество десятичных цифр, гарантированных для выживания text → float → text round-trip.max_digits10
это количество десятичных цифр, необходимое для гарантии правильного числа с плавающей запятой → текст → с плавающей запятой.Будут исключения для обоих, но эти значения дают минимальную гарантию. Прочитайте оригинальное предложение на max_digits10
для ясного примера, слова профессора В. Кэхана и дальнейшие детали. Большинство реализаций C ++ следуют IEEE 754 для своих типов данных с плавающей точкой. Для IEEE 754 float
, digits10
является 6
а также max_digits10
является 9
; для 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го значительная цифра сохранилась, а 7го цифра не сохранилась для первого числа. Тем не менее, все 27 цифр второй выжили; этот исключение Тем не менее, большинство цифр становится разным после 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
требуется, по крайней мере, устранять неоднозначность двух чисел с плавающей запятой в их десятичной форме, чтобы при преобразовании обратно в двоичное число мы снова получали исходные биты, а не немного до или после него из-за ошибок округления.
На мой взгляд, это достаточно объяснено на связанном сайте (и сайте для цифр10):
цифры10 — это (максимум) количество «десятичных» цифр, где цифры
может быть представлен типом в любом случае, независимо от их фактического значения.
Обычное 4-байтовое целое число без знака в качестве примера: как все должны знать, оно имеет ровно 32 бита,
это 32 цифры двоичного числа.
Но с точки зрения десятичных чисел?
Вероятно, 9.
Потому что он может хранить 100000000, а также 999999999.
Но если взять числа с 10 цифрами: 4000000000 можно сохранить, а 5000000000 нет.
Так что, если нам нужна гарантия минимальной десятичной разрядности, это 9.
И это результат цифр10.
max_digits10 интересен только для чисел с плавающей запятой / double … и дает количество десятичных цифр
который нам нужно вывести / сохранить / обработать … чтобы получить всю точность
тип с плавающей запятой может предложить.
Теоретический пример: переменная с содержанием 123.112233445566
Если вы показываете 123.11223344 пользователю, это не так точно, как может быть.
Если вы показываете 123.1122334455660000000 для пользователя, это не имеет смысла, потому что
Вы могли бы опустить завершающие нули (потому что ваша переменная не может держать так много в любом случае)
Следовательно, max_digits10 говорит о том, сколько цифр у вас есть в типе.