Почему FLT_MAX и FLT_MIN не являются положительной и отрицательной бесконечностью, и для чего они используются?
Логически говоря, учитывая природу значений с плавающей запятой, максимальные и минимальные представимые значения float
положительная и отрицательная бесконечность соответственно.
Почему же тогда FLT_MAX
а также FLT_MIN
не установлен им? Я понимаю, что это "как раз то, к чему призывает стандарт". Но тогда, что может использовать FLT_MAX
или же FLT_MIN
имеют, как они в настоящее время лежат в середине представимого числового диапазона float
? Другие числовые ограничения имеют некоторую полезность, потому что они дают гарантии относительно сравнений (например, "Ни один INT не может проверить больше, чем INT_MAX"). Без такой гарантии какая польза от этих ограничений?
Мотивирующий пример для C++:
#include <vector>
#include <limits>
template<typename T>
T find_min(const std::vector<T> &vec)
{
T result = std::numeric_limits<T>::max();
for (std::vector<T>::const_iterator p = vec.start() ; p != vec.end() ; ++p)
if (*p < result) result = *p;
return result;
}
Этот код работает нормально, если T является целочисленным типом, но не если это тип с плавающей запятой. Это раздражает. (Да, да, стандартная библиотека обеспечивает min_element
, но это не главное. Дело в шаблоне.)
4 ответа
Цель FLT_MIN
/ MAX
это сказать вам, что самые маленькие и самые большие представимые числа с плавающей точкой. Бесконечность не число; это предел.
какое использование могут иметь FLT_MAX или FLT_MIN, поскольку они в настоящее время лежат в середине представимого числового диапазона с плавающей точкой?
Они не лежат в середине или представительном диапазоне. Нет положительного значения с плавающей запятой x
который вы можете добавить к FLT_MAX
и получить представительное число. Вы получите +INF.
Этот код работает нормально, если T является целочисленным типом, но не если это тип с плавающей запятой. Это раздражает. (Да, да, стандартная библиотека предоставляет min_element, но это не главное. Дело в шаблоне.)
И как это не работает нормально? Это дает вам наименьшее значение. Единственная ситуация, когда он не "работает нормально", это если таблица содержит только +INF. И даже в этом случае он возвращает фактическое число, а не код ошибки. Что, пожалуй, лучший вариант в любом случае.
FLT_MAX
определяется в разделе 5.2.4.2.2(9) как
максимальное представимое конечное число с плавающей точкой
Положительная бесконечность не является конечной.
FLT_MIN
определяется в разделе 5.2.4.2.2(10) как
минимальное нормализованное положительное число с плавающей точкой
Отрицательная бесконечность не является ни нормированной, ни положительной.
Я бы сказал, что разбитый шаблон, который вы видите, является лишь артефактом плохого именования в C, тогда как в C++ с numeric_limits
и шаблоны, это настоящий семантический недостаток, который нарушает код шаблона, который хочет обрабатывать как целочисленные значения, так и значения с плавающей запятой. Конечно, вы можете написать немного дополнительного кода, чтобы проверить, есть ли у вас целочисленный тип или тип с плавающей запятой (например, if ((T)1/2) /* floating point */ else /* integer */
) и проблема уходит.
Что касается того, почему кто-то будет заботиться о ценностях FLT_MIN
а также FLT_MAX
дать вам, они полезны для предотвращения переполнения и переполнения. Например, предположим, мне нужно вычислить sqrt(x²-1)
, Это хорошо определено для любой плавающей запятой x
больше или равно 1, но выполнение возведения в квадрат, вычитания и квадратного корня может легко переполниться и сделать результат бессмысленным, когда x
большой. Можно было бы проверить, x > FLT_MAX/x
и обработать этот случай другим способом (например, просто вернуть x
:-).
В отличие от целочисленных типов, типы с плавающей точкой (почти?) Универсально симметричны относительно нуля, и я думаю, что модель C с плавающей точкой требует этого.
В системах с двумя дополнительными компонентами (т. Е. Почти во всех современных системах) INT_MIN
является -INT_MAX-1
; в других системах это может быть -INT_MAX
, (Quibble: система из двух дополнений может иметь INT_MIN
равно -INT_MAX
если самое низкое представимое значение рассматривается как представление ловушки.) Так INT_MIN
передает информацию, которая INT_MAX
само по себе это не так.
И макрос для наименьшего положительного значения не будет особенно полезен; это только 1.
В плавающей точке, с другой стороны, отрицательное значение с наибольшей величиной просто -FLT_MAX
(или же -DBL_MAX
, или же -LDBL_MAX
).
Что касается того, почему они не Infinity, уже есть способ представить бесконечные значения (по крайней мере, в C99): макрос INFINITY
, Это может вызвать проблемы для некоторых приложений C++, но они были определены для C, который не имеет таких вещей, как std::numeric_limits<T>::max()
,
Кроме того, не все системы с плавающей точкой имеют представления для бесконечности (или NaN).
Если FLT_MAX
мы INFINITY
(в системах, которые его поддерживают), тогда, возможно, потребуется еще один макрос для наибольшего представимого реального значения.