diff --git a/src/main/java/org/apache/commons/lang3/math/NumberUtils.java b/src/main/java/org/apache/commons/lang3/math/NumberUtils.java index 0637a5ac2cd..84b954bfd16 100644 --- a/src/main/java/org/apache/commons/lang3/math/NumberUtils.java +++ b/src/main/java/org/apache/commons/lang3/math/NumberUtils.java @@ -761,12 +761,7 @@ public static double max(final double... array) { // Finds and returns max double max = array[0]; for (int j = 1; j < array.length; j++) { - if (Double.isNaN(array[j])) { - return Double.NaN; - } - if (array[j] > max) { - max = array[j]; - } + max = Math.max(max, array[j]); } return max; } @@ -804,12 +799,7 @@ public static float max(final float... array) { // Finds and returns max float max = array[0]; for (int j = 1; j < array.length; j++) { - if (Float.isNaN(array[j])) { - return Float.NaN; - } - if (array[j] > max) { - max = array[j]; - } + max = Math.max(max, array[j]); } return max; } @@ -1042,12 +1032,7 @@ public static double min(final double... array) { // Finds and returns min double min = array[0]; for (int i = 1; i < array.length; i++) { - if (Double.isNaN(array[i])) { - return Double.NaN; - } - if (array[i] < min) { - min = array[i]; - } + min = Math.min(min, array[i]); } return min; } @@ -1085,12 +1070,7 @@ public static float min(final float... array) { // Finds and returns min float min = array[0]; for (int i = 1; i < array.length; i++) { - if (Float.isNaN(array[i])) { - return Float.NaN; - } - if (array[i] < min) { - min = array[i]; - } + min = Math.min(min, array[i]); } return min; } diff --git a/src/test/java/org/apache/commons/lang3/math/NumberUtilsTest.java b/src/test/java/org/apache/commons/lang3/math/NumberUtilsTest.java index dc0ac6450cd..ae8a45c7a82 100644 --- a/src/test/java/org/apache/commons/lang3/math/NumberUtilsTest.java +++ b/src/test/java/org/apache/commons/lang3/math/NumberUtilsTest.java @@ -1308,6 +1308,24 @@ void testLang381() { assertTrue(Float.isNaN(NumberUtils.max(bF))); } + @Test + void testMinMaxSignedZero() { + // The varargs overloads must agree with Math.min/Math.max (and the three-argument + // overloads, which delegate to them) on the sign of zero. -0.0 is distinct from 0.0, + // e.g. 1 / -0.0 is -Infinity, so the raw bits are asserted here. + assertEquals(Double.doubleToRawLongBits(0.0d), Double.doubleToRawLongBits(NumberUtils.max(-0.0d, 0.0d))); + assertEquals(Double.doubleToRawLongBits(0.0d), Double.doubleToRawLongBits(NumberUtils.max(0.0d, -0.0d))); + assertEquals(Double.doubleToRawLongBits(-0.0d), Double.doubleToRawLongBits(NumberUtils.min(-0.0d, 0.0d))); + assertEquals(Double.doubleToRawLongBits(-0.0d), Double.doubleToRawLongBits(NumberUtils.min(0.0d, -0.0d))); + assertEquals(Float.floatToRawIntBits(0.0f), Float.floatToRawIntBits(NumberUtils.max(-0.0f, 0.0f))); + assertEquals(Float.floatToRawIntBits(0.0f), Float.floatToRawIntBits(NumberUtils.max(0.0f, -0.0f))); + assertEquals(Float.floatToRawIntBits(-0.0f), Float.floatToRawIntBits(NumberUtils.min(-0.0f, 0.0f))); + assertEquals(Float.floatToRawIntBits(-0.0f), Float.floatToRawIntBits(NumberUtils.min(0.0f, -0.0f))); + // the varargs result matches the three-argument overload + assertEquals(Double.doubleToRawLongBits(NumberUtils.max(-0.0d, 0.0d, 0.0d)), Double.doubleToRawLongBits(NumberUtils.max(-0.0d, 0.0d))); + assertEquals(Double.doubleToRawLongBits(NumberUtils.min(0.0d, -0.0d, 0.0d)), Double.doubleToRawLongBits(NumberUtils.min(0.0d, -0.0d))); + } + @Test void testLang747() { assertEquals(Integer.valueOf(0x8000), NumberUtils.createNumber("0x8000"));