0

I see two possible implementations for a MAX macro in C. Which of these would be best?

  1. define MAX(X,Y) ((X) < (Y) ? : (Y) : (X))
  2. define MAX(X,Y) 0.5*(X+Y+ABS(X-Y))
Niklas Rosencrantz
  • 25,640
  • 75
  • 229
  • 424
  • 8
    The second choice is obfuscated, complicated, only works correctly with floating-point numbers, and uses floating-point arithmetic rather than comparisons and selections. Is there *any* reason you bring it up, or is this a test for StackOverflow users "just to see if you're paying attention"? – Kilian Foth Mar 21 '13 at 09:39
  • 1
    Intuitively (which is always a bad base for performance decisions) I'd say avoid floating point math when possible. Other than that: *benchmark it!* – Joachim Sauer Mar 21 '13 at 09:40
  • 2
    It's also work better if you removed the syntax error from the first option. – Kristof Provost Mar 21 '13 at 10:01
  • 7
    let's see... What would it return when used that way: `MAX(++x, --y)`, assuming prior values of x, y are 1, 2? – gnat Mar 21 '13 at 10:04
  • possible duplicate of [MIN and MAX in C](http://stackoverflow.com/questions/3437404/min-and-max-in-c) – Joris Timmermans Mar 21 '13 at 12:50

2 Answers2

4

Second one is hard to read, and actually broken. Really bad idea.

  1. Second one always uses doubles. You will get rounding errors. I certainly wouldn't expect getting a result that's not equal to either side.
  2. When applied to integers it returns a double, quite surprising. Floats get promoted to double as well.
  3. If you "fix" it by replacing *0.5 with /2 it'd "work" on those other types, but you'd get unexpected overflows on large integers.

I also recommend functions, and not macros so the arguments don't get evaluated twice.

There are occasionally situations where such tricky versions are appropriate. For example calculating the maximum of two integers in constant time. But they're rare, and certainly should not be used as the default implementation for MAX.

CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
  • 1
    Functions are a great recommendation, but they force you to choose a type. If you want `MAX` to work with any numeric type, without multiple evaluation, and without using gcc extensions (`({})`), you're (I think) stuck. – ugoren Mar 21 '13 at 12:01
2

The first version is more general, efficient and easier to understand.

The second version uses a floating-point constant, which makes it specific to doubles. It may potentially return the wrong answer since floating-point calculations may be rounded off. (due to the inability of a binary value to represent exactly every possible decimal value, 0.1 for example) There are also more calculations involved. The multiplication with 0.5 is not enclosed in parenthesis which may lead to unexpected results.

There's also the matter of compiler optimizations but I'm not going into that.

David
  • 943
  • 1
  • 10
  • 26