std::numeric_limits<T>::digits10
static const int digits10; | (до C++11) | |
static constexpr int digits10; | (начиная с C++11) |
Значение std::numeric_limits<T>::digits10 — это количество десятичных цифр, которые могут быть представлены типом T без изменений, то есть любое число с таким количеством значащих десятичных цифр можно преобразовать в значение типа T, а затем обратно в десятичную форму без изменений из-за округления или переполнения. Для типов с основанием системы счисления radix это значение digits() (digits - 1 для типов с плавающей запятой), умноженное на \(\small \log_{10}{radix}\)log10(radix) и округлённое вниз.
Стандартные специализации
T | значение std::numeric_limits<T>::digits10 |
|---|---|
| /* non-specialized */ |
0 |
| bool |
0 |
| char |
std::numeric_limits<char>::digits * std::log10(2) |
| signedchar |
std::numeric_limits<signed char>::digits * std::log10(2) |
| unsignedchar |
std::numeric_limits<unsigned char>::digits * std::log10(2) |
| wchar_t |
std::numeric_limits<wchar_t>::digits * std::log10(2) |
| char8_t (начиная с C++20) |
std::numeric_limits<char8_t>::digits * std::log10(2) |
| char16_t (начиная с C++11) |
std::numeric_limits<char16_t>::digits * std::log10(2) |
| char32_t (начиная с C++11) |
std::numeric_limits<char32_t>::digits * std::log10(2) |
| short |
std::numeric_limits<short>::digits * std::log10(2) |
| unsignedshort |
std::numeric_limits<unsigned short>::digits * std::log10(2) |
| int |
std::numeric_limits<int>::digits * std::log10(2) |
| unsignedint |
std::numeric_limits<unsigned int>::digits * std::log10(2) |
| long |
std::numeric_limits<long>::digits * std::log10(2) |
| unsignedlong |
std::numeric_limits<unsigned long>::digits * std::log10(2) |
| longlong (начиная с C++11) |
std::numeric_limits<long long>::digits * std::log10(2) |
| unsignedlonglong (начиная с C++11) |
std::numeric_limits<unsigned long long>::digits * std::log10(2) |
| float |
FLT_DIG (6 для IEEE float) |
| double |
DBL_DIG (15 для IEEE double) |
| longdouble |
LDBL_DIG (18 для 80-разрядного Intel longdouble; 33 для IEEE quadruple) |
Пример
8-разрядный двоичный тип может точно представлять любое десятичное число из двух цифр, но десятичные числа из трёх цифр в диапазоне 256..999 представить нельзя. Значение digits10 для 8-разрядного типа равно 2 (std::log10(2) ≈ 0.30103, поэтому 8 * std::log10(2) ≈ 2.41).
Стандартный 32-разрядный тип с плавающей запятой IEEE 754 имеет 24-разрядную дробную часть (23 разряда записываются явно, один подразумевается), что может навести на мысль, что он способен представлять десятичные числа из 7 цифр (24 * std::log10(2) ≈ 7.22), однако относительные ошибки округления неравномерны, и некоторые значения с плавающей запятой с 7 десятичными цифрами не сохраняются при преобразовании в 32-разрядное значение float и обратно: наименьший положительный пример — 8.589973e9, которое после обратного преобразования становится 8.589974e9. Эти ошибки округления не могут превышать одного разряда в представлении, а digits10 вычисляется как (24 - 1) * std::log10(2), что составляет примерно 6.92. Округление вниз даёт значение 6.
Аналогично, 16-значная строка 9007199254740993 не сохраняется при преобразовании text → double → text, превращаясь в 9007199254740992: тип double с плавающей запятой IEEE 754 шириной 64 разряда гарантирует такое обратное преобразование только для 15 десятичных цифр.
Пример
#include <concepts>
#include <iomanip>
#include <iostream>
#include <limits>
#include <meta>
#include <string_view>
#include <type_traits>
using namespace std::literals;
template<typename T>
requires std::integral<T> or std::floating_point<T>
constexpr void digit10()
{
constexpr int w{(int)"unsigned long long"sv.size()};
std::cout << std::right << std::setw(w)
<< std::meta::display_string_of(^^T) << " : "
<< std::numeric_limits<T>::digits10 << '\n';
}
template<typename... T>
constexpr void digits10()
{
(digit10<T>(), ...);
}
int main()
{
digits10<
bool, char, signed char, unsigned char, wchar_t, char8_t, char16_t,
char32_t, short, unsigned short, int, unsigned int, long, unsigned long,
long long, unsigned long long, float, double, long double
>();
}
Возможный вывод:
bool : 0
char : 2
signed char : 2
unsigned char : 2
wchar_t : 9
char8_t : 2
char16_t : 4
char32_t : 9
short : 4
unsigned short : 4
int : 9
unsigned int : 9
long : 18
unsigned long : 19
long long : 18
unsigned long long : 19
float : 6
double : 15
long double : 18
См. также
|
[static] (C++11) | количество десятичных цифр, необходимое для различения всех значений этого типа (открытая статическая константа-член) |
|
[static] | основание системы счисления, используемое для представления значений данного типа (открытая статическая константа-член) |
|
[static] | количество цифр radix, которые можно представить без изменений (открытая статическая константа-член) |
|
[static] | число на единицу больше наименьшей отрицательной степени основания системы счисления, которая является допустимым нормализованным значением с плавающей запятой (открытая статическая константа-член) |
|
[static] | число на единицу больше наибольшей целой степени основания системы счисления, которая является допустимым конечным значением с плавающей запятой (открытая статическая константа-член) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/types/numeric_limits/digits10