Подтвердить что ты не робот

Указывает ли стандарт С++ на представление чисел с плавающей запятой?

Для типов T, для которых std::is_floating_point<T>::value является true, указывает ли стандарт С++ что-то на пути, которым должен быть реализован T?

Например, T может даже следовать представлению sign/mantissa/exponent? Или может быть полностью произвольным?

4b9b3361

Ответ 1

От N3337:

[basic.fundamental/8]: Существует три типа с плавающей запятой: float, double и long double. Тип double обеспечивает не менее так же, как float, а double long double обеспечивает как минимум такую ​​же точность, как double. Набор значений типа float является подмножеством набора значений типа double; набор значений типа double является подмножеством набора значений типа long double. Значение представления типы с плавающей запятой определяются реализацией. Интегральные и плавающие типы совместно называются арифметическими типы. Специализации стандартного шаблона std:: numeric_limits (18.3) должны указывать максимальный и минимальные значения для каждого арифметического типа для реализации.

Если вы хотите проверить, использует ли ваша реализация IEEE-754, вы можете использовать std::numeric_limits::is_iec559:

static_assert(std::numeric_limits<double>::is_iec559,
              "This code requires IEEE-754 doubles");

В этой области есть ряд других вспомогательных признаков, таких как has_infinity, quiet_NaN и больше.

Ответ 2

Стандарт C имеет "приложение" (в C11 - Приложение F), в котором излагаются, что означает, что реализация C должна соответствовать стандарту IEC 60559, преемнику стандарта IEEE 754. Реализация, соответствующая Приложению F должны иметь номера с плавающей точкой представления IEEE. Однако осуществление этого приложения является необязательным; основной стандарт специально избегает говорить что-либо о представлении чисел с плавающей запятой.

Я не знаю, есть ли эквивалентное приложение для С++. Он не отображается в N3337, но это может означать, что он распространяется отдельно. Существование std::numeric_limits<floating-type>::is_iec559 указывает на то, что комитет С++ по крайней мере думал об этом, но, возможно, не так подробно, как это сделал комитет C. (Это и всегда было чертовски стыдно, что стандарт С++ не выражается как набор изменений для стандарта C.)

Ответ 3

Никакой конкретной реализации не требуется. Стандарт С++ вообще не говорит об этом. Стандарт C довольно подробно описывает концептуальную модель, предполагаемую для чисел с плавающей запятой, со знаком, показателем, значением в некоторой базе b и т.д. Однако он, в частности, заявляет, что это чисто описательное, а не требование об осуществлении (C11, сноска 21):

Модель с плавающей точкой предназначена для уточнения описания каждой характеристики с плавающей запятой и не требует, чтобы арифметика с плавающей запятой реализации была идентичной.

Тем не менее, хотя детали могут меняться, по крайней мере, из-за меня, мне кажется, что, производя (например) соответствующую реализацию double, которая не вполне соответствовала обычной модели (т.е. значению и экспоненте ) было бы сложно (или, по крайней мере, трудно сделать с конкурентоспособной производительностью, так или иначе). Было бы особенно сложно, если бы оно менялось другими способами, например, переупорядочиванием порядка или использованием другой базы.

Определение std::numeric_limits<T>::digitsstd::numeric_limits<T>::digits10) подразумевает справедливо, что то, что указано как тип с плавающей точкой, должно сохранять (по крайней мере приблизительно) ту же точность для всех чисел в довольно широком диапазоне величин. Самым очевидным способом добиться этого является наличие некоторого количества бит/цифр, посвященных значению, и некоторого другого (отдельного) набора бит, посвященного экспоненте.

Ответ 4

Идея std::is_floating_point заключается в том, чтобы сделать код пользователя разного происхождения лучше вместе. Технически вы можете указать int как std::is_floating_point, не вызывая поведения undefined. Но скажите, что у вас есть некоторая шаблонная библиотека, которая должна многократно делиться на T n. Для ускорения работы библиотека создает T ni = 1 / n и заменяет деление на n умножением на ni. Это отлично работает для чисел с плавающей запятой, но не для целых чисел. Поэтому библиотека корректно выполняет только оптимизацию, если std::is_floating_point<T>::value == true. Если вы лжете код, вероятно, все еще работает со стандартной точки зрения, но является неправильным с логической точки зрения. Поэтому, если вы пишете класс, который ведет себя как более крупный float, отметьте его как std::is_floating_point, иначе нет. Это должно обеспечить вам оптимальный и правильный код.