views:

513

answers:

5

How do I hard code an absolute maximum or minimum value for a float or double? I want to search out the max/min of an array by simply iterating through and catching the largest.

There are also positive and negative infinity for floats, should I use those instead? If so, how do I denote that in my code?

+20  A: 

You can use numeric_limits which is defined in <limits> to find the minimum or maximum value of types (As long as a specialization exists for the type). You can also use it to retrieve infinity (and put a - in front for negative infinity).

#include <limits>

//...

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

As noted in the comments, min() returns the lowest possible positive value. In other words the positive value closest to 0 that can be represented. The lowest possible value is the negative of the maximum possible value.

There is of course the std::max_element and min_element functions (defined in <algorithm>) which may be a better choice for finding the largest or smallest value in an array.

Yacoby
How do i use this exactly? What do i need to include? I don't think I've used something like this before.
Faken
Hmm...that max element function would have been very useful...this is what happens when you learn coding on your own and not formally. You end up reinventing the wheel 50 times over. This is just like the last time i learned about ceil(). Thank you.
Faken
@Yacoby, you might want to clarify that numeric_limits<float>::min() doesn't mean most negative value, it means smallest positive.
MSN
@MSN Good point, thanks for pointing that out.
Yacoby
+2  A: 

To manually find the minimum of an array you don't need to know the minimum value of float:

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

And similar code for the maximum value.

Bill
A: 

May I suggest that you initialize your "max and min so far" variables not to infinity, but to the first number in the array?

Thomas Padron-McCarthy
Bill was faster.
Thomas Padron-McCarthy
+6  A: 

There's no real need to initialize to smallest/largest possible to find the smallest/largest in the array:

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

Or, if you're doing it more than once:

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

The disadvantage of providing sample code -- I see others have already suggested the same idea.

Note that while the standard has a min_element and max_element, using these would require scanning through the data twice, which could be a problem if the array is large at all.

Edit: Addressing the problem of finding the smallest non-zero value in an array of unsigned: observe that unsigned values "wrap around" when they reach an extreme. To find the smallest non-zero value, we can subtract one from each for the comparison. Any zero values will "wrap around" to the largest possible value for the type, but the relationship between other values will be retained. After we're done, we obviously add one back to the value we found.

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

Note this still uses the first element for the initial value, but we still don't need any "special case" code -- since that will wrap around to the largest possible value, any non-zero value will compare as being smaller. The result will be the smallest nonzero value, or 0 if and only if the vector contained no non-zero values.

Jerry Coffin
But you get a +1 for it from me!
Dan Diplo
I initlize to max mins because sometimes i want the smallest non zero value (in an unsigned integer case for example, my data tends to have a lot of uninteresting zeros). It just seems to make sense to me to initialize it rather than preform extra checks to ensure the first element is not zero.
Faken
@Faken: Even then you can define a comparison function that treats zero as the largest possible value, so you can still use `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
@Jerry: C++0x will add minmax_element to address the problem you mention. (But then it won't be possible to ignore zeros...)
UncleBens
+1  A: 

You can either use -FLT_MAX (or -DBL_MAX) for the maximum magnitude negative number and FLT_MAX (or DBL_MAX) for positive. This gives you the range of possible float (or double) values.

You probably don't want to use FLT_MIN; it corresponds to the smallest magnitude positive number that can be represented with a float, not the most negative value representable with a float.

FLT_MIN and FLT_MAX correspond to std::numeric_limits<float>::min() and std::numeric_limits<float>::max().

MSN
I think I'll use this version actually, its simpler to remember and makes more scene to me. Integers i can just initialize using hexadecimal. Though, best answer still stays because the answer also introduced me to some new extremely useful functions.
Faken