1 2 Previous Next 24 Replies Latest reply: May 15, 2012 2:37 PM by baftos RSS

    Math.min() and Math.max(): should they still be limited to two arguments?

    936169
      Math.min() and Math.max() take exactly two arguments each. Since Java 5, both methods could very well take varargs, allowing programmers to write simpler code. So, instead of this:

      public static int min(int a, int b) {
      return (a <= b) ? a : b;
      }

      we could have something like this:

      public static int min(final int first, final int... others) {
      if ( (others==null) || (others.length==0) ) {
      return first;
      }

      int minimum=first;
      for (int a : others) {
      if (a < minimum) {
      minimum=a;
      }
      }

      return minimum;
      }

      And simplify everyone's life by allowing calls like max(1, 2, 3, 4).

      Yes, there are some issues to work out (for example, the method above won't accept min(x), where x is a int[] - a usage most programmers might expect to be accepted), but I think this would be a positive addition to the Math library (and StrictMath as well).

      I have no idea if this has been discussed to death before, so I'd like ask around first. What do you think?

      Thanks.
        • 1. Re: Math.min() and Math.max(): should they still be limited to two arguments?
          baftos
          I think it's good, but I would use only one vararg and return Integer.MIN_VALUE, Integer.MAX_VALUE for 0 values passed in. This also allows passing in arrays of any size.
          • 2. Re: Math.min() and Math.max(): should they still be limited to two arguments?
            936169
            I thought about that, but decided against it: MAX_VALUE is a valid value, and returning it if the array is null or empty would mask a deeper problem (namely, that min() or max() are being called with zero arguments); another possibility is to throw something like TooFewParametersException, but that would break a LOT of code and would be uncomfortable to handle with a try/catch).
            • 3. Re: Math.min() and Math.max(): should they still be limited to two arguments?
              796440
              933166 wrote:
              I thought about that, but decided against it: MAX_VALUE is a valid value, and returning it if the array is null or empty would mask a deeper problem (namely, that min() or max() are being called with zero arguments);
              That's what I thought too, until DrClap showed me the error of my ways. Go to this thread, and search for "identity element": Re: simple max method
              another possibility is to throw something like TooFewParametersException, but that would break a LOT of code and would be uncomfortable to handle with a try/catch).
              I still intuitively would go with this approach, but I'd make that an unchecked exception, since calling it with no args would indicate a bug. (Ultimately though, as DrClap points out, the mathematically correct result for min() with no args is MAX_VALUE.)
              • 4. Re: Math.min() and Math.max(): should they still be limited to two arguments?
                936169
                Taking the pure math approach in a Math library? That makes... a lot of sense. :-)

                With that in mind, the min() method would now look like this:

                public static int min(final int... candidates) {
                if ( (candidates==null) || (candidates.length==0) ) {
                return Integer.MAX_VALUE;
                }

                int minimum=Integer.MAX_VALUE;
                for (int a : candidates) {
                if (a < minimum) {
                minimum=a;
                }
                }

                return minimum;
                }

                Seems nice.

                There's still the issue of why weren't min() and max() modified to use varargs. An oversight? Was it rejected? Was there some disagreement over it?

                Should we write a JSR to have this considered?

                Should we do min() and max() methods for byte and short types as well?

                Thanks.

                Edited by: 933166 on May 9, 2012 11:08 AM (corrected a verb)
                • 5. Re: Math.min() and Math.max(): should they still be limited to two arguments?
                  baftos
                  933166 wrote:
                  There's still the issue of why weren't min() and max() modified to use varargs.
                  I don't think they can be 'modified'. They can only be overloaded, otherwise old code would stop working, unless recompiled.
                  • 6. Re: Math.min() and Math.max(): should they still be limited to two arguments?
                    EJP
                    There's still the issue of why weren't min() and max() modified to use varargs.
                    I doubt that it was even considered, but if it was, I'm sure it would have been rejected on efficiency grounds alone. I would certainly have made that argument in their place.
                    • 7. Re: Math.min() and Math.max(): should they still be limited to two arguments?
                      baftos
                      But if they keep the old methods, and I think they have to (see my post above), the most common use (2 arguments) will be as efficient as always. The other cases will be as efficient as can be written by experts, rather than having developers of unknown skill level write and re-write them.
                      • 8. Re: Math.min() and Math.max(): should they still be limited to two arguments?
                        EJP
                        The varargs cases involve autoboxing, so they can never be as efficient regardless of who writes them.
                        • 9. Re: Math.min() and Math.max(): should they still be limited to two arguments?
                          796440
                          EJP wrote:
                          The varargs cases involve autoboxing, so they can never be as efficient regardless of who writes them.
                          Are you sure? I thought int... just became int[] as far as the method was concerned. I haven't bothered to look it up in the JLS though.
                          • 10. Re: Math.min() and Math.max(): should they still be limited to two arguments?
                            EJP
                            Err, oops, yes. And the OP is wrong about the min(a) not compiling: it does.

                            OP's method could be written better as:
                            static int     min(int a1, int...a2)
                            {
                                 if (a2 != null)
                                      for (int a : a2)
                                           if (a1 > a)
                                                a1 = a;
                                 return a1;
                            }
                            (Insert the 'missing' braces to taste.)
                            • 11. Re: Math.min() and Math.max(): should they still be limited to two arguments?
                              936169
                              EJP wrote:
                              Err, oops, yes. And the OP is wrong about the min(a) not compiling: it does.

                              OP's method could be written better as:
                              static int     min(int a1, int...a2)
                              {
                                   if (a2 != null)
                                        for (int a : a2)
                                             if (a1 > a)
                                                  a1 = a;
                                   return a1;
                              }
                              (Insert the 'missing' braces to taste.)
                              I just tried it on both Java 6 and 7, and I get (as I expected) compiler errors. I'll quote:

                              ----
                              21:47:42 mod-cga@mail:~$ cat testmin1.java
                              public class testmin1 {

                              public static int min(final int first, final int... others) {
                              if ( (others==null) || (others.length==0) ) {
                              return first;
                              }

                              int minimum=first;
                              for (int a : others) {
                              if (a < minimum) {
                              minimum=a;
                              }
                              }

                              return minimum;
                              }



                              public static void main(String[] args) {
                              int[] x;

                              System.out.println(min(2, 1, 3, 4));

                              x=new int[] {42, 86, 13, 99};
                              System.out.println(min(x));

                              x=new int[] {1970};
                              System.out.println(min(x));

                              x=new int[] {};
                              System.out.println(min(x));

                              x=null;
                              System.out.println(min(x));
                              }

                              }

                              21:47:49 mod-cga@mail:~$ javac -version
                              javac 1.6.0_20
                              21:47:57 mod-cga@mail:~$ javac testmin1.java
                              testmin1.java:26: min(int,int...) in testmin1 cannot be applied to (int[])
                              System.out.println(min(x));
                              ^
                              testmin1.java:29: min(int,int...) in testmin1 cannot be applied to (int[])
                              System.out.println(min(x));
                              ^
                              testmin1.java:32: min(int,int...) in testmin1 cannot be applied to (int[])
                              System.out.println(min(x));
                              ^
                              testmin1.java:35: min(int,int...) in testmin1 cannot be applied to (int[])
                              System.out.println(min(x));
                              ^
                              4 errors
                              21:48:03 mod-cga@mail:~$
                              ----


                              ----
                              [C:\TEMP]ver/R

                              TCC 13.03.47 Windows XP [Version 5.1.2600]
                              TCC Build 47 Windows XP Build 2600 Service Pack 3
                              Registered to Miguel Farah

                              [C:\TEMP]javac -version
                              javac 1.7.0_03

                              [C:\TEMP]javac testmin1.java
                              testmin1.java:26: error: method min in class testmin1 cannot be applied to given types;
                              System.out.println(min(x));
                              ^
                              required: int,int[]
                              found: int[]
                              reason: actual argument int[] cannot be converted to int by method invocation conversion
                              testmin1.java:29: error: method min in class testmin1 cannot be applied to given types;
                              System.out.println(min(x));
                              ^
                              required: int,int[]
                              found: int[]
                              reason: actual argument int[] cannot be converted to int by method invocation conversion
                              testmin1.java:32: error: method min in class testmin1 cannot be applied to given types;
                              System.out.println(min(x));
                              ^
                              required: int,int[]
                              found: int[]
                              reason: actual argument int[] cannot be converted to int by method invocation conversion
                              testmin1.java:35: error: method min in class testmin1 cannot be applied to given types;
                              System.out.println(min(x));
                              ^
                              required: int,int[]
                              found: int[]
                              reason: actual argument int[] cannot be converted to int by method invocation conversion
                              4 errors

                              [C:\TEMP]
                              ----


                              Still, the issue seems to be moot, as the second min() implementation [ min(final int... candidates) ] seems better suited.
                              • 12. Re: Math.min() and Math.max(): should they still be limited to two arguments?
                                EJP
                                I don't know why you would construct argument arrays when the varargs syntax already does it for you. min(1), min(1, 2) and min(1,2,3) all compile. You could rewrite either method as min(int...a) to cover those extra cases, but the result wouldn't be binary-compatible with the existing Math.min().
                                • 13. Re: Math.min() and Math.max(): should they still be limited to two arguments?
                                  936169
                                  EJP wrote:
                                  I don't know why you would construct argument arrays when the varargs syntax already does it for you. min(1), min(1, 2) and min(1,2,3) all compile. You could rewrite either method as min(int...a) to cover those extra cases, but the result wouldn't be binary-compatible with the existing Math.min().
                                  I'm trying to take into account those situations where the user needs to find the minimum inside an array. I'm sure we can all agree that something like:
                                  min(arr[0], arr[1], arr[2], arr[3])
                                  makes no sense, especially if the array's length isn't known beforehand. The natural thing to do is to simply call:
                                  min(arr)
                                  • 14. Re: Math.min() and Math.max(): should they still be limited to two arguments?
                                    EJP
                                    I was about to reconsider my last answer.

                                    Passing zero arguments makes no sense: there is no expected behaviour.

                                    So passing an array which can be empty doesn't make much sense either, for the same reason.

                                    So there has to be at least one value.

                                    The simplest way of ensuring that is at compile time, by making it min(int, int...).

                                    Otherwise you have to add runtime checks and whatever the new behaviour is supposed to be, which is vulnerable to the counter-argument from adverse performance, and to another one about adding unexpected behaviour, IOW throwing some RumtimeException if there are no values, which is the only sensible choice I can see.

                                    Your case is met by min(arr[0], arr), which has one redundant step in it but delivers the correct result.
                                    1 2 Previous Next