Почему 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 (в системах, которые его поддерживают), тогда, возможно, потребуется еще один макрос для наибольшего представимого реального значения.

Другие вопросы по тегам