как мне инициализировать поплавок его максимальным / минимальным значением?

100

Как жестко запрограммировать абсолютное максимальное или минимальное значение для чисел с плавающей запятой или двойных чисел? Я хочу найти максимальное / минимальное значение массива, просто перебирая и выбирая самый большой.

Есть также положительная и отрицательная бесконечность для поплавков, следует ли мне использовать их вместо них? Если да, как это обозначить в моем коде?

Подделка
источник

Ответы:

152

Вы можете использовать std::numeric_limitswhich is defined in, <limits>чтобы найти минимальное или максимальное значение типов (если для типа существует специализация). Вы также можете использовать его для получения бесконечности (и поставить -перед отрицательной бесконечностью).

#include <limits>

//...

std::numeric_limits<float>::max();
std::numeric_limits<float>::min();
std::numeric_limits<float>::infinity();

Как отмечено в комментариях, min()возвращает минимально возможное положительное значение. Другими словами, положительное значение, наиболее близкое к 0, которое может быть представлено. Наименьшее возможное значение - это отрицательное значение максимально возможного значения.

Конечно, std::max_elementсуществуют функции и min_element (определенные в <algorithm>), которые могут быть лучшим выбором для поиска наибольшего или наименьшего значения в массиве.

Якоби
источник
Как мне это использовать? Что мне нужно включить? Не думаю, что раньше использовал что-то подобное.
Faken
Хм ... эта функция max element была бы очень полезна ... вот что происходит, когда вы изучаете кодирование самостоятельно, а не формально. Вы в конечном итоге 50 раз изобретаете колесо. Это как в последний раз, когда я узнал о ceil (). Спасибо.
Faken
18
@Yacoby, вы можете пояснить, что numeric_limits <float> :: min () не означает наибольшее отрицательное значение, это означает наименьшее положительное значение.
MSN
13
@killogre: добавлен C ++ 11 numeric_limits<T>::lowest(), который возвращает наименьшее (отрицательное) значение, возможное для типа, чтобы решить эту проблему.
Cornstalks
3
std::numeric_limits<float>::min()никак не дает наименьшее положительное значение , которое может быть представлено; он дает наименьшее нормальное число с плавающей запятой одинарной точности. Между нулем и этим числом также есть субнормальные числа. В частности, std::numeric_limits<float>::min()дает, 1.17549e-38но наименьшее представимое субнормальное число с плавающей запятой равно nextafterf(0.0f, 1.0f) == 1.4013e-45f.
nibot
45

Вы можете использовать -FLT_MAX(или -DBL_MAX) для максимального отрицательного числа и FLT_MAX(или DBL_MAX) для положительного. Это дает вам диапазон возможных значений с плавающей запятой (или двойным).

Вероятно, вы не хотите использовать FLT_MIN; оно соответствует наименьшему положительному числу, которое может быть представлено с помощью числа с плавающей запятой, а не самому отрицательному значению, которое может быть представлено с помощью числа с плавающей запятой.

FLT_MINи FLT_MAXсоответствуют std::numeric_limits<float>::min()и std::numeric_limits<float>::max().

MSN
источник
Я думаю, что на самом деле буду использовать эту версию, ее проще запомнить и она создает для меня больше сцен. Целые числа, которые я могу просто инициализировать с помощью шестнадцатеричного числа. Хотя лучший ответ по-прежнему остается, потому что он также познакомил меня с некоторыми новыми чрезвычайно полезными функциями.
Faken
2
«[ FLT_MIN] соответствует наименьшему положительному числу, которое может быть представлено с помощью числа с плавающей запятой» - Это неверно . Это наименьшее нормальное число. Есть еще и субнормальные числа.
нибот
Вы хотите получить FLT_TRUE_MINнаименьшее возможное число с плавающей запятой, что соответствуетstd::numeric_limits<float>::denorm_min()
Крис Додд
17

Нет реальной необходимости инициализировать наименьшее / наибольшее возможное, чтобы найти наименьшее / наибольшее в массиве:

double largest = smallest = array[0];
for (int i=1; i<array_size; i++) {
    if (array[i] < smallest)
        smallest = array[i];
    if (array[i] > largest0
        largest= array[i];
}

Или, если вы делаете это более одного раза:

#include <utility>

template <class iter>
std::pair<typename iter::value_type, typename iter::value_type> find_extrema(iter begin, iter end) {
    std::pair<typename iter::value_type, typename iter::value_type> ret;
    ret.first = ret.second = *begin;
    while (++begin != end) {
        if (*begin < ret.first)
           ret.first = *begin;
        if (*begin > ret.second)
           ret.second = *begin;
   }
   return ret;
}

Недостаток предоставления образца кода - я вижу, что другие уже предлагали ту же идею.

Обратите внимание, что хотя в стандарте есть min_element и max_element, их использование потребует двойного сканирования данных, что может быть проблемой, если массив вообще большой. Последние стандарты решили эту проблему, добавив a std::minmax_element, который делает то же самое, что и find_extremaвыше (находит как минимальные, так и максимальные элементы в коллекции за один проход).

Изменить: Решение проблемы поиска наименьшего ненулевого значения в массиве беззнаковых: обратите внимание, что беззнаковые значения «оборачиваются», когда достигают крайних значений. Чтобы найти наименьшее ненулевое значение, мы можем вычесть из каждого по единице для сравнения. Любые нулевые значения будут "переходить" в максимально возможное значение для типа, но связь между другими значениями будет сохранена. После того, как мы закончили, мы, очевидно, добавляем единицу к найденному значению.

unsigned int min_nonzero(std::vector<unsigned int> const &values) { 
    if (vector.size() == 0)
        return 0;
    unsigned int temp = values[0]-1;
    for (int i=1; i<values.size(); i++)
        if (values[i]-1 < temp)
            temp = values[i]-1;
    return temp+1;
}

Обратите внимание, что здесь по-прежнему используется первый элемент в качестве начального значения, но нам по-прежнему не нужен какой-либо код «особого случая» - так как он будет завершен до максимально возможного значения, любое ненулевое значение будет сравниваться как меньшее. Результатом будет наименьшее ненулевое значение или 0, если и только если вектор не содержал ненулевых значений.

Джерри Гроб
источник
Но вы получаете от меня +1!
Дэн Дипло
1
Я инициализирую максимальное количество минут, потому что иногда мне нужно наименьшее ненулевое значение (например, в случае беззнакового целого числа, мои данные имеют много неинтересных нулей). Мне кажется, что имеет смысл инициализировать его, а не выполнять дополнительные проверки, чтобы убедиться, что первый элемент не равен нулю.
Faken
@Faken: Даже в этом случае вы можете определить функцию сравнения, которая рассматривает ноль как максимально возможное значение, поэтому вы все равно можете использовать std::min_element:bool less_ignoring_zero(unsigned a, unsigned b) { if (a == 0) return false; if (b == 0) return true; return a < b; }
UncleBens
2
@Jerry: C ++ 0x добавит minmax_element для решения упомянутой проблемы. (Но тогда игнорировать нули будет невозможно ...)
UncleBens
1
Что делать, если первый элемент недоступен во время инициализации? Это часто случается в онлайн-обработке (например, в boost ::
Accumulators
5

Чтобы вручную найти минимум массива, вам не нужно знать минимальное значение float:

float myFloats[];
...
float minimum = myFloats[0];
for (int i = 0; i < myFloatsSize; ++i)
{
  if (myFloats[i] < minimum)
  {
    minimum = myFloats[i];
  }
}

И аналогичный код для максимального значения.

Билл
источник
4

Могу я предложить вам инициализировать переменные «max и min пока» не до бесконечности, а до первого числа в массиве?

Томас Падрон-Маккарти
источник