For a lot of utility-type methods, the apache commons libraries have solid implementations that you can either leverage or get additional insight from. In this case, there is a method for finding the smallest of three doubles available in org.apache.commons.lang.math.NumberUtils. Their implementation is actually nearly identical to your initial thought:
public static double min(double a, double b, double c) {
return Math.min(Math.min(a, b), c);
}
Answer from wpgreenway on Stack OverflowFor a lot of utility-type methods, the apache commons libraries have solid implementations that you can either leverage or get additional insight from. In this case, there is a method for finding the smallest of three doubles available in org.apache.commons.lang.math.NumberUtils. Their implementation is actually nearly identical to your initial thought:
public static double min(double a, double b, double c) {
return Math.min(Math.min(a, b), c);
}
No, it's seriously not worth changing. The sort of improvements you're going to get when fiddling with micro-optimisations like this will not be worth it. Even the method call cost will be removed if the min function is called enough.
If you have a problem with your algorithm, your best bet is to look into macro-optimisations ("big picture" stuff like algorithm selection or tuning) - you'll generally get much better performance improvements there.
And your comment that removing Math.pow gave improvements may well be correct but that's because it's a relatively expensive operation. Math.min will not even be close to that in terms of cost.
Videos
To me it looks pretty readable
To me it doesn't.
Bugs:
The following method calls all incorrectly print 0:
System.out.println(min(3, 2, 2));
System.out.println(min(3, 3, 3));
System.out.println(min(1, 3, 3));
System.out.println(min(4, 2, 4));
This is because, when taking a look at your original code, it is overly complicated.
if( a < b && a < c && b < c) result = a ;
else if( a < b && a < c && b > c) result = a ;
Does it really matter if b < c or b > c? No, it doesn't here. And if b == c then neither of these current ones would be true which does the return 0. So that's a giant bug waiting to happen.
So those two first if's should be shortened into:
if (a <= b && a <= c) return a;
Note that I'm using <= here so that the case of all three having the same value gets handled correctly. Now also there's an early return so we don't need all these else.
If we group the rest of your statements according to what they return, we have for return b:
else if( a > b && a < c && b < c) result = b ;
else if( a > b && b < c && a > c) result = b ;
Which, if we always use b as the first operand and completely ignore whether or not a < c or a > c (and again, a == c is not handled here) we get:
if (b <= a && b <= c) return b;
Doing the same for c:
if (c <= a && c <= b) return c;
As one of a, b or c really has to be smallest, you can throw an exception if neither one of them is:
public static int min(int a, int b, int c) {
if (a <= b && a <= c) return a;
if (b <= a && b <= c) return b;
if (c <= a && c <= b) return c;
throw new AssertionError("No value is smallest, how did that happen?");
}
Or, if you don't like that exception:
public static int min(int a, int b, int c) {
if (a <= b && a <= c) return a;
if (b <= a && b <= c) return b;
return c;
}
This is in my opinion significantly better than your original version.
However, I would recommend Pimgd's solution, either an array or using chained Math.min.
For these things we have java.lang.Math:
public static int min(final int a, final int b, final int c){
return Math.min(a, Math.min(b, c));
}
Wow, look how short it is!
But it's 3 numbers today, it's 10 tomorrow.
As an alternative, how about an array?
public static int min(int... numbers){
if (numbers.length == 0){
throw new IllegalArgumentException("Can't determine smallest element in an empty set");
}
int smallest = numbers[0];
for (int i = 1; i < numbers.length; i++){
smallest = Math.min(smallest, numbers[i]);
}
return smallest;
}
I'd use the java.lang.Math solution, it's very short, and very readable.
int
public static int min(int a, int b) {
return (a <= b) ? a : b;
}
long
public static long min(long a, long b) {
return (a <= b) ? a : b;
}
float
public static float min(float a, float b) {
if (a != a) return a; // a is NaN
if ((a == 0.0f) && (b == 0.0f) && (Float.floatToIntBits(b) == negativeZeroFloatBits)) {
return b;
}
return (a <= b) ? a : b;
}
double
public static double min(double a, double b) {
if (a != a) return a; // a is NaN
if ((a == 0.0d) && (b == 0.0d) && (Double.doubleToLongBits(b) == negativeZeroDoubleBits)) {
return b;
}
return (a <= b) ? a : b;
}
More info: Here
Java 7 documentation:
Returns the smaller of two int values. That is, the result the argument closer to the value of Integer.MIN_VALUE. If the arguments have the same value, the result is that same value.
Behaviour:
Math.min(1, 2) => 1
Math.min(1F, 2) => 1F
Math.min(3D, 2F) => 2D
Math.min(-0F, 0F) => -0F
Math.min(0D, -0D) => -0D
Math.min(Float.NaN, -2) => Float.NaN
Math.min(-2F, Double.NaN) => Double.NaN
java.lang.Math and java.lang.StrictMath Source:
public static int min(int a, int b) {
return (a <= b) ? a : b;
}
java.lang.Math Bytecode (javap -c Math.class of Oracle's JDK's JRE's rt.jar):
public static int min(int, int);
Code:
0: iload_0 // loads a onto the stack
1: iload_1 // loads b onto the stack
2: if_icmpgt 9 // pops two ints (a, b) from the stack
// and compares them
// if b>a, the jvm continues at label 9
// else, at the next instruction, 5
// icmpgt is for integer-compare-greater-than
5: iload_0 // loads a onto the stack
6: goto 10 // jumps to label 10
9: iload_1 // loads
10: ireturn // returns the currently loaded integer
If the comparison at 5 is true, a will be loaded, the jvm will jump to 10 and return a, if the comparison yields false, it will jump to 9, which will load and return b.
Intrinsics:
This .hpp file of the Java 8 Hotspot JVM hints that it optimizes Math.min even further with optimized machine code:
do_intrinsic(_min, java_lang_Math, min_name, int2_int_signature, F_S)
This means the above bytecode won't be executed by the Java 8 Hotspot JVM. However, this differs from JVM to JVM, which is why I also explained the bytecode!
Hopefully, now you know all there is to know about Math.min! :)
Hint:
A method that accepts 3 (integer) parameters would look like this ...
public static int findMin(int p1, int p2, int p3) {
...
}
You're about 99% of the way there, the only problem you have is the fact that findMin should take three parameters, not one.
findMin should look more like...
public static int findMin(int num1, int num2, int num3) {
Then, instead of using 5, 7, and 3 directly, you would use num1, num2, num3 in there place.
Then you would call the method using something like...
int min = findMin(5, 7, 3);
Don't forget to assign the resulting value from the method call ;)
You may find Defining Methods of some help