tags:

views:

3501

answers:

11

From C++, are min and max preferable over fmin and fmax? For comparing two integers, do they provide basically the same functionality?

Do you tend to use one of these sets of functions or do you prefer to write your own (perhaps to improve efficiency, portability, flexibility, etc.)?

Notes:

  1. The C++ Standard Template Library (STL) declares the min and max functions in the standard C++ algorithm header.

  2. The C standard (C99) provides the fmin and fmax function in the standard C math.h header.

Thanks in advance!

+1  A: 

I always use the min and max macros for ints. I'm not sure why anyone would use fmin or fmax for integer values.

The big gotcha with min and max is that they're not functions, even if they look like them. If you do something like:

min (10, BigExpensiveFunctionCall())

That function call may get called twice depending on the implementation of the macro. As such, its best practice in my org to never call min or max with things that aren't a literal or variable.

popester
std::min isn't a macro...
Cogwheel - Matthew Orlando
min and max are often implemented as macros in C, but this is C++, where they're implemented as templates. Much, much better.
David Thornley
If you `#include <windows.h>`, you get `min` and `max` defined as macros. This will conflict with `std::min` and `std::max`, so you need to compile your sources with `#define NOMINMAX` to exclude the former.
Steve Guidi
It would have been nice if Microsoft put a `#ifdef _WINDOWS #undef min` in their `<algorithm>` header. Saves me the effort
MSalters
+14  A: 

fmin and fmax are specifically for use with floating point numbers (hence the "f"). If you use it for ints, you may suffer performance losses due to conversion and/or lack of inlining.

std::min and std::max are template functions which work on any type with a less-than (<) operator, so they can operate on any data type that allows such a comparison. You can also provide your own comparison function if you don't want it to work off <.

Cogwheel - Matthew Orlando
Warning: min and max can only compare two variables of the exact same type... so you can't compare an int and a double with them :(
Matthieu M.
True - max(1, 2.0) doesn't work, it has to be something like max<double>(1, 2.0) or max(double(1), 2.0).
David Thornley
Which is a Good Thing™ IMO :)
Cogwheel - Matthew Orlando
That's a big assumption that there will be a cost for conversion. On some systems the only difference will be loading the values into an FPU Regester rather than a normal register before comparison.
Martin York
Well yeah, pretty much every statement about C++ performance depends on the compiler/system. :P I'll change "'ll" to " may"...
Cogwheel - Matthew Orlando
Are there any platforms with 64-bit ints (ILP64) and 64-bit doubles? On those platforms, converting from int to double would result in a loss of precision for extremely positive/negative ints.
bk1e
+3  A: 

I would prefer the C++ min/max functions, if you are using C++, because they are type-specific. fmin/fmax will force everything to be converted to/from floating point.

Also, the C++ min/max functions will work with user-defined types as long as you have defined operator< for those types.

HTH,

Eric Melski
Electric Cloud, Inc.

Eric Melski
+2  A: 

std::min and std::max are templates. So, they can be used on a variety of types that provide the less than operator, including floats, doubles, long doubles. So, if you wanted to write generic C++ code you'd do something like this:

template<typename T>
T const& max3(T const& a, T const& b, T const& c)
{
   using std::max;
   return max(max(a,b),c); // non-qualified max allows ADL
}

As for performance, I don't think fmin and fmax differ from their C++ counterparts.

sellibitze
What is ADL, and why do we want it here?
Rob Kennedy
@Rob Kennedy: http://en.wikipedia.org/wiki/Argument_dependent_name_lookup
bk1e
ADL = argument dependent lookup. In this case it is probably not necessary because every user-defined type that comes with its own max-function is likely to provide a special less than operator as well. It's just a habit of mine that I write code like this -- primarily with `swap` and some numerical functions like `abs`. You would *want* to use a type's special swap and abs functions instead of the generic ones in case the special ones exist. I suggest reading Herb Sutter's article about "namespaces and the interface principle": http://www.gotw.ca/publications/mill08.htm
sellibitze
A: 

fmin and fmax are only for floating point and double variables.

min and max are template functions that allow comparison of any types, given a binary predicate. They can also be used with other algorithms to provide complex functionality.

Marcin
+2  A: 

As you noted yourself, fmin and fmax were introduced in C99. Standard C++ library doesn't have fmin and fmax functions. Until C99 standard library gets incorporated into C++ (if ever), the application areas of these functions are cleanly separated. There's no situation where you might have to "prefer" one over the other.

You just use templated std::min/std::max in C++, and use whatever is available in C.

AndreyT
+1  A: 

If your implementation provides a 64-bit integer type, you may get a different (incorrect) answer by using fmin or fmax. Your 64-bit integers will be converted to doubles, which will (at least usually) have a significand that's smaller than 64-bits. When you convert such a number to a double, some of the least significant bits can/will be lost completely.

This means that two numbers that were really different could end up equal when converted to double -- and the result will be that incorrect number, that's not necessarily equal to either of the original inputs.

Jerry Coffin
A: 

fmin and fmax, of fminl and fmaxl could be preferred when comparing signed and unsigned integers - you can take advantage of the fact that the entire range of signed and unsigned numbers and you don't have to worry about integer ranges and promotions.

unsigned int x = 4000000000;
int y = -1;

int z = min(x, y);
z = (int)fmin(x, y);
Eclipse
+1  A: 

Use std::min and std::max.

If the other versions are faster then your implementation can add overloads for these and you'll get the benefit of performance and portability:

template <typename T>
T min (T, T) {
  // ... default
}

inline float min (float f1, float f2) {
 return fmin( f1, f2);
}
Richard Corden
A: 

As Richard Corden pointed, use C++ functions min and max defined in std namespace. They provide type safety, and help to avoid comparing mixed types (i.e. float point vs integer) what sometimes may be undesirable.

If you find that C++ library you use defines min/max as macros as well, it may cause conflicts, then you can prevent unwanted macro substitution calling the min/max functions this way (notice extra brackets):

(std::min)(x, y)
(std::max)(x, y)

Remember, this will effectively disable Argument Dependant Lookup (ADL, also called Koenig lookup), in case you want to rely on ADL.

mloskot