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