Ответ 1
Я считаю, что clang здесь соответствует, если мы читаем ответ на std :: stod throws out_of_range error для строки, которая должна быть действительной, она говорит:
Стандарт C++ позволяет конверсиям строк
double
отчет о нижнем уровне, если результат находится в субнормальном диапазоне, даже если он представлен.7.63918 • 10 -313 находится в пределах
double
, но находится в субнормальном диапазоне. Стандарт C++ говорит, чтоstod
вызываетstrtod
а затем отсылает к стандарту C для определенияstrtod
. Стандарт C указывает на то, чтоstrtod
может переполняться, о чем говорится: "Результат заканчивается, если величина математического результата настолько мала, что математический результат не может быть представлен без особой ошибки округления в объекте указанного типа". Это неловкое выражение, но оно относится к ошибкам округления, которые возникают при возникновении субнормальных значений. (Субнормальные значения подвержены более крупным относительным ошибкам, чем нормальные значения, поэтому их ошибки округления могут считаться экстраординарными).Таким образом, реализация C++ разрешена стандартом C++ до нижнего уровня для субнормальных значений, даже если они являются представимыми.
Мы можем подтвердить, что мы полагаемся на strtod из [facet.num.get.virtuals] p3.3.4:
- Для двойного значения используется функция strtod.
Мы можем проверить это с помощью этой небольшой программы (см. Ее в прямом эфире):
void check(const char* p)
{
std::string str{p};
printf( "errno before: %d\n", errno ) ;
double val = std::strtod(str.c_str(), nullptr);
printf( "val: %g\n", val ) ;
printf( "errno after: %d\n", errno ) ;
printf( "ERANGE value: %d\n", ERANGE ) ;
}
int main()
{
check("9.99989e-321") ;
}
который имеет следующий результат:
errno before: 0
val: 9.99989e-321
errno after: 34
ERANGE value: 34
C11 в 7.22.1.3p10 говорит нам:
Функции возвращают преобразованное значение, если оно есть. Если преобразование не может быть выполнено, возвращается ноль. Если правильное значение переполнения и округление по умолчанию действует (7.12.1), возвращается плюс или минус HUGE_VAL, HUGE_VALF или HUGE_VALL (в соответствии с типом возврата и значком значения), и сохраняется значение макроса ERANGE в errno. Если результат заканчивается (7.12.1), функции возвращают значение, величина которого не больше наименьшего нормализованного положительного числа в возвращаемом типе; независимо от того, получает ли errno значение ERANGE, оно определяется реализацией.
POSIX использует это соглашение:
[ERANGE]
Возвращаемое значение приведет к переполнению или недопущению.
Мы можем проверить, является ли он субнормальным через fpclassify (см. Его в прямом эфире).