Ответ 1
Вы можете использовать библиотеки Boost. Библиотека Numeric Conversions предоставляет класс под названием bounds, который может использоваться последовательно.
Смотрите документацию здесь.
Черты numeric_limits должны быть общим способом получения информации различного типа, чтобы иметь возможность делать такие вещи, как
template<typename T>
T min(const std::vector<T>& vect)
{
T val = std::numeric_limits<T>::min();
for(int i=0 ; i<vect.size() ; i++)
val = max(T, vect[i]);
return val;
}
Проблема заключается в том, что (по крайней мере, с использованием MS Visual Studio 2008) numeric_limits <int> :: min() возвращает наименьшее отрицательное число, а numeric_limits <double> :: min() возвращает наименьшее положительное число!
Кто-нибудь знает рациональность этого дизайна? Есть ли лучший (рекомендуемый?) Способ использования numeric_limits? В моей конкретной функции выше я мог бы, конечно, инициализировать T для vect [0], но это не тот ответ, который я ищу.
См. также (обсуждение с плавающей запятой) здесь
Вы можете использовать библиотеки Boost. Библиотека Numeric Conversions предоставляет класс под названием bounds, который может использоваться последовательно.
Смотрите документацию здесь.
Это старый поток, но есть обновленный ответ:
С++ 11 добавила функцию lowest()
в std::numeric_limits
(Смотрите здесь)
Итак, теперь вы можете вызвать std::numeric_limits<double>::lowest()
, чтобы получить наименьшее представляемое отрицательное значение.
Поведение min() не так уж и странно, оно возвращает FLT_MIN
, DBL_MIN
или INT_MIN
(или их соответствующие значения) в зависимости от типа, с которым вы специализируетесь. Поэтому ваш вопрос должен быть в том, почему FLT_MIN
и DBL_MIN
определяются иначе, чем INT_MIN
.
К сожалению, я не знаю ответа на этот последний вопрос.
Мое подозрение в том, что он был определен таким образом для практических целей. Для целых чисел вы обычно относитесь к переполнению/нижнему потоку, где интерес представляет минимальное и максимальное значение.
Для чисел с плавающей запятой существует различный вид нижнего потока в том, что вычисление может привести к значению, которое больше нуля, но меньше наименьшего представляемого десятичного числа для этого типа с плавающей запятой. Зная, что наименьшее представляемое значение с плавающей запятой позволяет обойти проблему. См. Также статью Википедии о subnormal/denormal числа.
Обходной путь был бы
double val = -std::numeric_limits<double>::max();
Конечно, это не объясняет странное поведение численных_лимит:: min(), что может быть связано с тем, что для целых чисел существуют разные границы min/max (min = -2 ^ n, max = 2 ^ n-1), но не для удвоений.
Можно утверждать определение наименьшего значения для пустого вектора. Если вектор пуст, то не существует наименьшего элемента.
Предпочитаете вместо std:: min_element:
int main()
{
std::vector<int> v;
std::generate_n(std::back_inserter(v), 1000, std::rand);
std::vector<int>::iterator it = std::min_element(v.begin(), v.end());
if (it == v.end())
{
std::cout << "There is no smallest element" << std::endl;
}
else
{
std::cout << "The smallest element is " << *it << std::endl;
}
}
Я не уверен в обосновании, но это ожидаемое поведение. Ну, в том смысле, как это описывает Josuttis (и, предположительно, стандарт)!
min(): "Минимальное конечное значение (минимум нормированное значение для с плавающей запятой типы с денормализацией).
Насколько я знаю, тип не является целым числом (numeric_limits<>::is_integer
) и имеет денормализацию (numeric_limits<>::has_denorm
) min()
будет возвращать наименьшее представляемое значение этим типом. В противном случае он вернет наименьшее значение, которое может быть отрицательным.
Для более последовательного интерфейса просмотрите библиотеку Boost numeric/conversion. В частности, bounds
класс признаков. Вот фрагмент:
cout << "lowest float:" << boost::numeric::bounds<float>::lowest();
cout << "lowest int: " << boost::numeric::bounds<int>::lowest();
Вы также можете найти boost:: integer library. Он приносит некоторую поддержку целочисленного C99 (например, int_least16_t
) на С++ и может помочь выбрать наиболее подходящий для вас тип. Пример:
boost::uint_t<20>::fast fastest20bits; // fastest unsigned integer that
// can hold at least 20 bits.
boost::int_max_value_t<100000>::least // smallest integer that can store
// the value 100000.
Я часто нахожу, что когда мне нужен один из boost:: numeric/conversion или boost:: integer, мне нужны они оба.
numeric_limits<int>::min
возвратил отрицательное число low, все типы чисел с плавающей запятой, вернул положительное число наименьшее, когда я попробовал его с помощью Sun CC и g++.
Я думаю, это потому, что "наименьший" и "минимальный" означают разные вещи с номерами с плавающей запятой. Это немного странно.
Оба Sun CC и g++ дают одинаковый результат:
short: min: -32768 max: 32767
int: min: -2147483648 max: 2147483647
unsigned int: min: 0 max: 4294967295
long: мин: -2147483648 max: 2147483647
float: мин: 1.17549e-38 max: 3.40282e + 38
double: min: 2.22507e-308 max: 1.79769e + 308
длинный двойной: мин.: 3.3621e-4932 макс: 1.18973e + 4932
unsigned short: min: 0 max: 65535
unsigned int: min: 0 max: 4294967295
unsigned long: min: 0 max: 429496729
template<typename T>
void showMinMax()
{
cout << "min: " << numeric_limits<T>::min() << endl;
cout << "max: " << numeric_limits<T>::max() << endl;
cout << endl;
}
int main()
{
cout << "short:";
showMinMax<short>()
...etc...etc..