como inicializo um float para seu valor máximo / mínimo?

100

Como faço para codificar um valor absoluto máximo ou mínimo para um float ou double? Quero pesquisar o máximo / mínimo de uma matriz simplesmente iterando e pegando a maior.

Existem também infinitos positivos e negativos para flutuadores, devo usá-los? Em caso afirmativo, como denoto isso em meu código?

Faken
fonte

Respostas:

151

Você pode usar o std::numeric_limitsque está definido em <limits>para encontrar o valor mínimo ou máximo dos tipos (desde que exista uma especialização para o tipo). Você também pode usá-lo para recuperar o infinito (e colocar um -na frente para o infinito negativo).

#include <limits>

//...

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

Conforme observado nos comentários, min()retorna o menor valor positivo possível. Em outras palavras, o valor positivo mais próximo de 0 que pode ser representado. O menor valor possível é o negativo do valor máximo possível.

Existem, é claro, as std::max_elementfunções e min_element (definidas em <algorithm>), que podem ser uma escolha melhor para encontrar o maior ou o menor valor em um array.

Yacoby
fonte
Como faço para usar isso exatamente? O que eu preciso incluir? Acho que não usei algo assim antes.
Faken de
Hmm ... aquela função de elemento max teria sido muito útil ... isso é o que acontece quando você aprende a codificação por conta própria e não formalmente. Você acaba reinventando a roda 50 vezes. É como a última vez que aprendi sobre ceil (). Obrigado.
Faken
18
@Yacoby, você pode querer esclarecer que numeric_limits <float> :: min () não significa o valor mais negativo, significa o menor positivo.
MSN
13
@killogre: C ++ 11 adicionado numeric_limits<T>::lowest(), que retorna o menor valor (negativo) possível para o tipo para resolver este problema.
Cornstalks
3
std::numeric_limits<float>::min()que não dão o valor positivo menor que pode ser representado; ele fornece o menor número normal de ponto flutuante de precisão única. Também existem números subnormais entre zero e este número. Em particular, std::numeric_limits<float>::min()dá , 1.17549e-38mas o menor flutuante subnormal representável é nextafterf(0.0f, 1.0f) == 1.4013e-45f.
nibot de
45

Você pode usar -FLT_MAX(ou -DBL_MAX) para o número negativo de magnitude máxima e FLT_MAX(ou DBL_MAX) para positivo. Isso fornece a faixa de valores flutuantes (ou duplos) possíveis.

Você provavelmente não deseja usar FLT_MIN; ele corresponde ao menor número positivo de magnitude que pode ser representado com um float, não o valor mais negativo representável com um float.

FLT_MINe FLT_MAXcorrespondem a std::numeric_limits<float>::min()e std::numeric_limits<float>::max().

MSN
fonte
Acho que vou usar essa versão na verdade, é mais simples de lembrar e faz mais cena para mim. Inteiros, posso apenas inicializar usando hexadecimal. Porém, a melhor resposta ainda permanece porque a resposta também me apresentou a algumas novas funções extremamente úteis.
Faken de
2
"[ FLT_MIN] corresponde ao menor número positivo de magnitude que pode ser representado com um flutuador" - Isso não é verdade . É o menor número normal . Também existem números subnormais.
nibot de
Você deseja FLT_TRUE_MINa menor flutuação real possível, que corresponde astd::numeric_limits<float>::denorm_min()
Chris Dodd
17

Não há necessidade real de inicializar para o menor / maior possível para encontrar o menor / maior na matriz:

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];
}

Ou, se você estiver fazendo isso mais de uma vez:

#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;
}

A desvantagem de fornecer um código de amostra - vejo que outros já sugeriram a mesma ideia.

Observe que, embora o padrão tenha um min_element e max_element, usá-los exigiria a varredura dos dados duas vezes, o que poderia ser um problema se o array fosse grande. Padrões recentes trataram disso adicionando um std::minmax_element, que faz o mesmo que o find_extremaanterior (encontre os elementos mínimo e máximo em uma coleção em uma única passagem).

Edit: Resolvendo o problema de encontrar o menor valor diferente de zero em uma matriz de não assinados: observe que os valores não assinados "envolvem" quando atingem um extremo. Para encontrar o menor valor diferente de zero, podemos subtrair um de cada para a comparação. Quaisquer valores zero serão "agrupados" no maior valor possível para o tipo, mas a relação entre os outros valores será mantida. Depois de terminarmos, obviamente adicionamos um de volta ao valor que encontramos.

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;
}

Observe que isso ainda usa o primeiro elemento para o valor inicial, mas ainda não precisamos de nenhum código de "caso especial" - uma vez que isso envolverá o maior valor possível, qualquer valor diferente de zero será comparado como sendo menor. O resultado será o menor valor diferente de zero, ou 0 se e somente se o vetor não contiver valores diferentes de zero.

Jerry Coffin
fonte
Mas você ganha um +1 de mim!
Dan Diplo de
1
Eu inicializo para minutos máximos porque às vezes eu quero o menor valor diferente de zero (em um caso de inteiro sem sinal, por exemplo, meus dados tendem a ter muitos zeros desinteressantes). Para mim, parece fazer sentido inicializá-lo em vez de realizar verificações extras para garantir que o primeiro elemento não seja zero.
Faken de
@Faken: Mesmo assim, você pode definir uma função de comparação que trata zero como o maior valor possível, então você ainda pode usar 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 adicionará minmax_element para resolver o problema que você mencionou. (Mas então não será possível ignorar zeros ...)
UncleBens
1
E se o primeiro elemento não estiver disponível no momento da inicialização? Isso acontece muito no processamento online (como em boost ::
Accumulators
5

Para encontrar manualmente o mínimo de uma matriz, você não precisa saber o valor mínimo de float:

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

E um código semelhante para o valor máximo.

Conta
fonte
4

Posso sugerir que você inicialize suas variáveis ​​"máx. E mín. Até agora" não para o infinito, mas para o primeiro número na matriz?

Thomas Padron-McCarthy
fonte