Почему FLT_MAX и FLT_MIN не являются положительной и отрицательной бесконечностью и каково их использование?

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

Почему же тогда FLT_MAX и FLT_MIN не установлены на них? Я понимаю, что это "то, как требовался стандарт". Но тогда , что может использовать FLT_MAX или FLT_MIN, поскольку они в настоящее время лежат в середине представленного числового диапазона float? Другие числовые ограничения имеют некоторую полезность, потому что они дают гарантии относительно сравнений (например, "Нет INT может тестировать больше, чем INT_MAX" ). Без такой гарантии, какими будут эти ограничения на плавание?

Мотивационный пример для С++:

#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, но это не точка. Точка - это шаблон.)

Ответ 1

Цель FLT_MIN/MAX - рассказать вам, какие наименьшие и наибольшие представляемые числа с плавающей запятой . Бесконечность не число; это предел.

какое использование может иметь FLT_MAX или FLT_MIN, поскольку они в настоящее время лежат в середине представленного числового диапазона float?

Они не лежат в середине или представимом диапазоне. Не существует положительного значения float x, которое вы можете добавить в FLT_MAX и получить представимое число. Вы получите + INF.

Этот код отлично работает, если T является интегральным типом, но не если он является типом с плавающей точкой. Это раздражает. (Да, стандартная библиотека предоставляет min_element, но это не точка. Точка - это шаблон.)

И как это не работает? Это дает вам наименьшее значение. Единственная ситуация, когда он не работает "отлично", заключается в том, что таблица содержит только + INF. И даже в этом случае он возвращает фактическое число, а не код ошибки. Вероятно, это лучший вариант.

Ответ 2

FLT_MAX определяется в разделе 5.2.4.2.2 (9) как

Максимально представимое конечное число с плавающей запятой

Положительная бесконечность не является конечной.

FLT_MIN определяется в разделе 5.2.4.2.2 (10) как

минимальное нормированное положительное число с плавающей запятой

Отрицательная бесконечность не является ни нормированной, ни положительной.

Ответ 3

Я бы сказал, что разбитый шаблон, который вы видите, является только артефактом плохого именования на 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: -).

Ответ 4

В отличие от целых типов, типы с плавающей запятой (почти?) универсально симметричны относительно нуля, и я думаю, что для этой модели требуется с плавающей запятой.

В системах с двумя дополнениями (т.е. почти во всех современных системах) INT_MIN есть -INT_MAX-1; в других системах это может быть -INT_MAX. (Quibble: система с двумя дополнениями может иметь INT_MIN, равную -INT_MAX, если наименьшее представимое значение рассматривается как ловушечное представление.) Таким образом, INT_MIN передает информацию, что INT_MAX сама по себе не делает.

И макрос для наименьшего положительного значения не будет особенно полезен; что только 1.

В плавающей точке, с другой стороны, отрицательное значение с наибольшей величиной составляет всего -FLT_MAX (или -DBL_MAX или -LDBL_MAX).

Что касается того, почему они не Бесконечность, уже существует способ представления бесконечных значений (по крайней мере, на C99): макрос INFINITY. Это может вызвать проблемы для некоторых приложений на С++, но они были определены для C, у которого нет таких вещей, как std::numeric_limits<T>::max().

Кроме того, не все системы с плавающей запятой имеют представления для бесконечности (или NaN).

Если FLT_MAX были INFINITY (в системах, которые его поддерживают), тогда, вероятно, для наибольшего представляемого реального значения, вероятно, должен быть другой макрос.