| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.commons.numbers.core; |
| |
| import java.math.RoundingMode; |
| |
| import org.junit.jupiter.api.Assertions; |
| import org.junit.jupiter.api.Test; |
| |
| /** |
| * Test cases for the {@link Precision} class. |
| * |
| */ |
| public class PrecisionTest { |
| |
| // Interfaces to allow testing equals variants with the same conditions |
| |
| @FunctionalInterface |
| private interface EqualsWithDelta { |
| boolean equals(double a, double b, double delta); |
| } |
| |
| @FunctionalInterface |
| private interface EqualsWithUlps { |
| boolean equals(double a, double b, int ulps); |
| } |
| |
| @FunctionalInterface |
| private interface FloatEqualsWithDelta { |
| boolean equals(float a, float b, float delta); |
| } |
| |
| @FunctionalInterface |
| private interface FloatEqualsWithUlps { |
| boolean equals(float a, float b, int ulps); |
| } |
| |
| @Test |
| void testEqualsWithRelativeTolerance() { |
| Assertions.assertTrue(Precision.equalsWithRelativeTolerance(0d, 0d, 0d)); |
| Assertions.assertTrue(Precision.equalsWithRelativeTolerance(0d, 1 / Double.NEGATIVE_INFINITY, 0d)); |
| |
| final double eps = 1e-14; |
| Assertions.assertFalse(Precision.equalsWithRelativeTolerance(1.987654687654968, 1.987654687654988, eps)); |
| Assertions.assertTrue(Precision.equalsWithRelativeTolerance(1.987654687654968, 1.987654687654987, eps)); |
| Assertions.assertFalse(Precision.equalsWithRelativeTolerance(1.987654687654968, 1.987654687654948, eps)); |
| Assertions.assertTrue(Precision.equalsWithRelativeTolerance(1.987654687654968, 1.987654687654949, eps)); |
| |
| Assertions.assertFalse(Precision.equalsWithRelativeTolerance(Precision.SAFE_MIN, 0.0, eps)); |
| |
| Assertions.assertFalse(Precision.equalsWithRelativeTolerance(1.0000000000001e-300, 1e-300, eps)); |
| Assertions.assertTrue(Precision.equalsWithRelativeTolerance(1.00000000000001e-300, 1e-300, eps)); |
| |
| Assertions.assertFalse(Precision.equalsWithRelativeTolerance(Double.NEGATIVE_INFINITY, 1.23, eps)); |
| Assertions.assertFalse(Precision.equalsWithRelativeTolerance(Double.POSITIVE_INFINITY, 1.23, eps)); |
| |
| Assertions.assertTrue(Precision.equalsWithRelativeTolerance(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, eps)); |
| Assertions.assertTrue(Precision.equalsWithRelativeTolerance(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, eps)); |
| Assertions.assertFalse(Precision.equalsWithRelativeTolerance(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, eps)); |
| |
| Assertions.assertFalse(Precision.equalsWithRelativeTolerance(Double.NaN, 1.23, eps)); |
| Assertions.assertFalse(Precision.equalsWithRelativeTolerance(Double.NaN, Double.NaN, eps)); |
| } |
| |
| @Test |
| void testEqualsIncludingNaN() { |
| double[] testArray = { |
| Double.NaN, |
| Double.POSITIVE_INFINITY, |
| Double.NEGATIVE_INFINITY, |
| 1d, |
| 0d }; |
| for (int i = 0; i < testArray.length; i++) { |
| for (int j = 0; j < testArray.length; j++) { |
| if (i == j) { |
| Assertions.assertTrue(Precision.equalsIncludingNaN(testArray[i], testArray[j])); |
| Assertions.assertTrue(Precision.equalsIncludingNaN(testArray[j], testArray[i])); |
| } else { |
| Assertions.assertFalse(Precision.equalsIncludingNaN(testArray[i], testArray[j])); |
| Assertions.assertFalse(Precision.equalsIncludingNaN(testArray[j], testArray[i])); |
| } |
| } |
| } |
| } |
| |
| @Test |
| void testEqualsWithAllowedDelta() { |
| assertEqualsWithAllowedDelta(Precision::equalsIncludingNaN, true); |
| } |
| |
| @Test |
| void testEqualsIncludingNaNWithAllowedDelta() { |
| assertEqualsWithAllowedDelta(Precision::equalsIncludingNaN, true); |
| } |
| |
| private static void assertEqualsWithAllowedDelta(EqualsWithDelta fun, boolean nanAreEqual) { |
| Assertions.assertTrue(fun.equals(153.0000, 153.0000, .0625)); |
| Assertions.assertTrue(fun.equals(153.0000, 153.0625, .0625)); |
| Assertions.assertTrue(fun.equals(152.9375, 153.0000, .0625)); |
| Assertions.assertFalse(fun.equals(153.0000, 153.0625, .0624)); |
| Assertions.assertFalse(fun.equals(152.9374, 153.0000, .0625)); |
| Assertions.assertEquals(nanAreEqual, fun.equals(Double.NaN, Double.NaN, 1.0)); |
| Assertions.assertTrue(fun.equals(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, 1.0)); |
| Assertions.assertTrue(fun.equals(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, 1.0)); |
| Assertions.assertFalse(fun.equals(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 1.0)); |
| } |
| |
| @Test |
| void testEqualsWithAllowedUlps() { |
| assertEqualsIncludingNaNWithAllowedUlps(Precision::equals, false, false); |
| } |
| |
| @Test |
| void testEqualsWithImplicitAllowedUlpsOf1() { |
| // Use the version without the ulp argument |
| assertEqualsIncludingNaNWithAllowedUlps((a, b, ulp) -> Precision.equals(a, b), false, true); |
| } |
| |
| @Test |
| void testEqualsIncludingNaNWithAllowedUlps() { |
| assertEqualsIncludingNaNWithAllowedUlps(Precision::equalsIncludingNaN, true, false); |
| } |
| |
| private static void assertEqualsIncludingNaNWithAllowedUlps(EqualsWithUlps fun, |
| boolean nanAreEqual, boolean fixed1Ulp) { |
| Assertions.assertTrue(fun.equals(0.0, -0.0, 1)); |
| |
| Assertions.assertTrue(fun.equals(1.0, 1 + Math.ulp(1d), 1)); |
| Assertions.assertFalse(fun.equals(1.0, 1 + 2 * Math.ulp(1d), 1)); |
| |
| for (double value : new double[] {153.0, -128.0, 0.0, 1.0}) { |
| Assertions.assertTrue(fun.equals(value, value, 1)); |
| Assertions.assertTrue(fun.equals(value, Math.nextUp(value), 1)); |
| Assertions.assertFalse(fun.equals(value, Math.nextUp(Math.nextUp(value)), 1)); |
| Assertions.assertTrue(fun.equals(value, Math.nextDown(value), 1)); |
| Assertions.assertFalse(fun.equals(value, Math.nextDown(Math.nextDown(value)), 1)); |
| // This test is conditional |
| if (!fixed1Ulp) { |
| Assertions.assertFalse(fun.equals(value, Math.nextUp(value), 0)); |
| Assertions.assertTrue(fun.equals(value, Math.nextUp(Math.nextUp(value)), 2)); |
| Assertions.assertTrue(fun.equals(value, Math.nextDown(Math.nextDown(value)), 2)); |
| } |
| } |
| |
| Assertions.assertTrue(fun.equals(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, 1)); |
| Assertions.assertTrue(fun.equals(Double.MAX_VALUE, Double.POSITIVE_INFINITY, 1)); |
| |
| Assertions.assertTrue(fun.equals(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, 1)); |
| Assertions.assertTrue(fun.equals(-Double.MAX_VALUE, Double.NEGATIVE_INFINITY, 1)); |
| |
| Assertions.assertEquals(nanAreEqual, fun.equals(Double.NaN, Double.NaN, 1)); |
| Assertions.assertEquals(nanAreEqual, fun.equals(Double.NaN, Double.NaN, 0)); |
| Assertions.assertFalse(fun.equals(Double.NaN, 0, 0)); |
| Assertions.assertFalse(fun.equals(0, Double.NaN, 0)); |
| Assertions.assertFalse(fun.equals(Double.NaN, Double.POSITIVE_INFINITY, 0)); |
| Assertions.assertFalse(fun.equals(Double.NaN, Double.NEGATIVE_INFINITY, 0)); |
| |
| Assertions.assertFalse(fun.equals(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 100000)); |
| } |
| |
| // Tests for floating point equality match the above tests with arguments |
| // converted to float |
| |
| @Test |
| void testFloatEqualsIncludingNaN() { |
| float[] testArray = { |
| Float.NaN, |
| Float.POSITIVE_INFINITY, |
| Float.NEGATIVE_INFINITY, |
| 1f, |
| 0f }; |
| for (int i = 0; i < testArray.length; i++) { |
| for (int j = 0; j < testArray.length; j++) { |
| if (i == j) { |
| Assertions.assertTrue(Precision.equalsIncludingNaN(testArray[i], testArray[j])); |
| Assertions.assertTrue(Precision.equalsIncludingNaN(testArray[j], testArray[i])); |
| } else { |
| Assertions.assertFalse(Precision.equalsIncludingNaN(testArray[i], testArray[j])); |
| Assertions.assertFalse(Precision.equalsIncludingNaN(testArray[j], testArray[i])); |
| } |
| } |
| } |
| } |
| |
| @Test |
| void testFloatEqualsWithAllowedDelta() { |
| assertFloatEqualsWithAllowedDelta(Precision::equalsIncludingNaN, true); |
| } |
| |
| @Test |
| void testFloatEqualsIncludingNaNWithAllowedDelta() { |
| assertFloatEqualsWithAllowedDelta(Precision::equalsIncludingNaN, true); |
| } |
| |
| private static void assertFloatEqualsWithAllowedDelta(FloatEqualsWithDelta fun, boolean nanAreEqual) { |
| Assertions.assertTrue(fun.equals(153.0000f, 153.0000f, .0625f)); |
| Assertions.assertTrue(fun.equals(153.0000f, 153.0625f, .0625f)); |
| Assertions.assertTrue(fun.equals(152.9375f, 153.0000f, .0625f)); |
| Assertions.assertFalse(fun.equals(153.0000f, 153.0625f, .0624f)); |
| Assertions.assertFalse(fun.equals(152.9374f, 153.0000f, .0625f)); |
| Assertions.assertEquals(nanAreEqual, fun.equals(Float.NaN, Float.NaN, 1.0f)); |
| Assertions.assertTrue(fun.equals(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY, 1.0f)); |
| Assertions.assertTrue(fun.equals(Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY, 1.0f)); |
| Assertions.assertFalse(fun.equals(Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY, 1.0f)); |
| } |
| |
| @Test |
| void testFloatEqualsWithAllowedUlps() { |
| assertFloatEqualsIncludingNaNWithAllowedUlps(Precision::equals, false, false); |
| } |
| |
| @Test |
| void testFloatEqualsWithImplicitAllowedUlpsOf1() { |
| // Use the version without the ulp argument |
| assertFloatEqualsIncludingNaNWithAllowedUlps((a, b, ulp) -> Precision.equals(a, b), false, true); |
| } |
| |
| @Test |
| void testFloatEqualsIncludingNaNWithAllowedUlps() { |
| assertFloatEqualsIncludingNaNWithAllowedUlps(Precision::equalsIncludingNaN, true, false); |
| } |
| |
| private static void assertFloatEqualsIncludingNaNWithAllowedUlps(FloatEqualsWithUlps fun, |
| boolean nanAreEqual, boolean fixed1Ulp) { |
| Assertions.assertTrue(fun.equals(0.0f, -0.0f, 1)); |
| |
| Assertions.assertTrue(fun.equals(1.0f, 1f + Math.ulp(1f), 1)); |
| Assertions.assertFalse(fun.equals(1.0f, 1f + 2 * Math.ulp(1f), 1)); |
| |
| for (float value : new float[] {153.0f, -128.0f, 0.0f, 1.0f}) { |
| Assertions.assertTrue(fun.equals(value, value, 1)); |
| Assertions.assertTrue(fun.equals(value, Math.nextUp(value), 1)); |
| Assertions.assertFalse(fun.equals(value, Math.nextUp(Math.nextUp(value)), 1)); |
| Assertions.assertTrue(fun.equals(value, Math.nextDown(value), 1)); |
| Assertions.assertFalse(fun.equals(value, Math.nextDown(Math.nextDown(value)), 1)); |
| // This test is conditional |
| if (!fixed1Ulp) { |
| Assertions.assertFalse(fun.equals(value, Math.nextUp(value), 0)); |
| Assertions.assertTrue(fun.equals(value, Math.nextUp(Math.nextUp(value)), 2)); |
| Assertions.assertTrue(fun.equals(value, Math.nextDown(Math.nextDown(value)), 2)); |
| } |
| } |
| |
| Assertions.assertTrue(fun.equals(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY, 1)); |
| Assertions.assertTrue(fun.equals(Float.MAX_VALUE, Float.POSITIVE_INFINITY, 1)); |
| |
| Assertions.assertTrue(fun.equals(Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY, 1)); |
| Assertions.assertTrue(fun.equals(-Float.MAX_VALUE, Float.NEGATIVE_INFINITY, 1)); |
| |
| Assertions.assertEquals(nanAreEqual, fun.equals(Float.NaN, Float.NaN, 1)); |
| Assertions.assertEquals(nanAreEqual, fun.equals(Float.NaN, Float.NaN, 0)); |
| Assertions.assertFalse(fun.equals(Float.NaN, 0, 0)); |
| Assertions.assertFalse(fun.equals(0, Float.NaN, 0)); |
| Assertions.assertFalse(fun.equals(Float.NaN, Float.POSITIVE_INFINITY, 0)); |
| Assertions.assertFalse(fun.equals(Float.NaN, Float.NEGATIVE_INFINITY, 0)); |
| |
| Assertions.assertFalse(fun.equals(Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY, 100000)); |
| } |
| |
| @Test |
| void testCompareToEpsilon() { |
| Assertions.assertEquals(0, Precision.compareTo(152.33, 152.32, .011)); |
| Assertions.assertTrue(Precision.compareTo(152.308, 152.32, .011) < 0); |
| Assertions.assertTrue(Precision.compareTo(152.33, 152.318, .011) > 0); |
| Assertions.assertEquals(0, Precision.compareTo(Double.MIN_VALUE, +0.0, Double.MIN_VALUE)); |
| Assertions.assertEquals(0, Precision.compareTo(Double.MIN_VALUE, -0.0, Double.MIN_VALUE)); |
| } |
| |
| @Test |
| void testCompareToMaxUlps() { |
| double a = 152.32; |
| double delta = Math.ulp(a); |
| for (int i = 0; i <= 10; ++i) { |
| if (i <= 5) { |
| Assertions.assertEquals(+0, Precision.compareTo(a, a + i * delta, 5)); |
| Assertions.assertEquals(+0, Precision.compareTo(a, a - i * delta, 5)); |
| } else { |
| Assertions.assertEquals(-1, Precision.compareTo(a, a + i * delta, 5)); |
| Assertions.assertEquals(+1, Precision.compareTo(a, a - i * delta, 5)); |
| } |
| } |
| |
| Assertions.assertEquals(+0, Precision.compareTo(-0.0, 0.0, 0)); |
| |
| Assertions.assertEquals(-1, Precision.compareTo(-Double.MIN_VALUE, -0.0, 0)); |
| Assertions.assertEquals(+0, Precision.compareTo(-Double.MIN_VALUE, -0.0, 1)); |
| Assertions.assertEquals(-1, Precision.compareTo(-Double.MIN_VALUE, +0.0, 0)); |
| Assertions.assertEquals(+0, Precision.compareTo(-Double.MIN_VALUE, +0.0, 1)); |
| |
| Assertions.assertEquals(+1, Precision.compareTo(+Double.MIN_VALUE, -0.0, 0)); |
| Assertions.assertEquals(+0, Precision.compareTo(+Double.MIN_VALUE, -0.0, 1)); |
| Assertions.assertEquals(+1, Precision.compareTo(+Double.MIN_VALUE, +0.0, 0)); |
| Assertions.assertEquals(+0, Precision.compareTo(+Double.MIN_VALUE, +0.0, 1)); |
| |
| Assertions.assertEquals(-1, Precision.compareTo(-Double.MIN_VALUE, Double.MIN_VALUE, 0)); |
| Assertions.assertEquals(-1, Precision.compareTo(-Double.MIN_VALUE, Double.MIN_VALUE, 1)); |
| Assertions.assertEquals(+0, Precision.compareTo(-Double.MIN_VALUE, Double.MIN_VALUE, 2)); |
| |
| Assertions.assertEquals(+0, Precision.compareTo(Double.MAX_VALUE, Double.POSITIVE_INFINITY, 1)); |
| Assertions.assertEquals(-1, Precision.compareTo(Double.MAX_VALUE, Double.POSITIVE_INFINITY, 0)); |
| |
| Assertions.assertEquals(+1, Precision.compareTo(Double.MAX_VALUE, Double.NaN, Integer.MAX_VALUE)); |
| Assertions.assertEquals(+1, Precision.compareTo(Double.NaN, Double.MAX_VALUE, Integer.MAX_VALUE)); |
| } |
| |
| @Test |
| void testRoundDouble() { |
| double x = 1.234567890; |
| Assertions.assertEquals(1.23, Precision.round(x, 2), 0.0); |
| Assertions.assertEquals(1.235, Precision.round(x, 3), 0.0); |
| Assertions.assertEquals(1.2346, Precision.round(x, 4), 0.0); |
| |
| // JIRA MATH-151 |
| Assertions.assertEquals(39.25, Precision.round(39.245, 2), 0.0); |
| Assertions.assertEquals(39.24, Precision.round(39.245, 2, RoundingMode.DOWN), 0.0); |
| double xx = 39.0; |
| xx += 245d / 1000d; |
| Assertions.assertEquals(39.25, Precision.round(xx, 2), 0.0); |
| |
| // BZ 35904 |
| Assertions.assertEquals(30.1d, Precision.round(30.095d, 2), 0.0d); |
| Assertions.assertEquals(30.1d, Precision.round(30.095d, 1), 0.0d); |
| Assertions.assertEquals(33.1d, Precision.round(33.095d, 1), 0.0d); |
| Assertions.assertEquals(33.1d, Precision.round(33.095d, 2), 0.0d); |
| Assertions.assertEquals(50.09d, Precision.round(50.085d, 2), 0.0d); |
| Assertions.assertEquals(50.19d, Precision.round(50.185d, 2), 0.0d); |
| Assertions.assertEquals(50.01d, Precision.round(50.005d, 2), 0.0d); |
| Assertions.assertEquals(30.01d, Precision.round(30.005d, 2), 0.0d); |
| Assertions.assertEquals(30.65d, Precision.round(30.645d, 2), 0.0d); |
| |
| Assertions.assertEquals(1.24, Precision.round(x, 2, RoundingMode.CEILING), 0.0); |
| Assertions.assertEquals(1.235, Precision.round(x, 3, RoundingMode.CEILING), 0.0); |
| Assertions.assertEquals(1.2346, Precision.round(x, 4, RoundingMode.CEILING), 0.0); |
| Assertions.assertEquals(-1.23, Precision.round(-x, 2, RoundingMode.CEILING), 0.0); |
| Assertions.assertEquals(-1.234, Precision.round(-x, 3, RoundingMode.CEILING), 0.0); |
| Assertions.assertEquals(-1.2345, Precision.round(-x, 4, RoundingMode.CEILING), 0.0); |
| |
| Assertions.assertEquals(1.23, Precision.round(x, 2, RoundingMode.DOWN), 0.0); |
| Assertions.assertEquals(1.234, Precision.round(x, 3, RoundingMode.DOWN), 0.0); |
| Assertions.assertEquals(1.2345, Precision.round(x, 4, RoundingMode.DOWN), 0.0); |
| Assertions.assertEquals(-1.23, Precision.round(-x, 2, RoundingMode.DOWN), 0.0); |
| Assertions.assertEquals(-1.234, Precision.round(-x, 3, RoundingMode.DOWN), 0.0); |
| Assertions.assertEquals(-1.2345, Precision.round(-x, 4, RoundingMode.DOWN), 0.0); |
| |
| Assertions.assertEquals(1.23, Precision.round(x, 2, RoundingMode.FLOOR), 0.0); |
| Assertions.assertEquals(1.234, Precision.round(x, 3, RoundingMode.FLOOR), 0.0); |
| Assertions.assertEquals(1.2345, Precision.round(x, 4, RoundingMode.FLOOR), 0.0); |
| Assertions.assertEquals(-1.24, Precision.round(-x, 2, RoundingMode.FLOOR), 0.0); |
| Assertions.assertEquals(-1.235, Precision.round(-x, 3, RoundingMode.FLOOR), 0.0); |
| Assertions.assertEquals(-1.2346, Precision.round(-x, 4, RoundingMode.FLOOR), 0.0); |
| |
| Assertions.assertEquals(1.23, Precision.round(x, 2, RoundingMode.HALF_DOWN), 0.0); |
| Assertions.assertEquals(1.235, Precision.round(x, 3, RoundingMode.HALF_DOWN), 0.0); |
| Assertions.assertEquals(1.2346, Precision.round(x, 4, RoundingMode.HALF_DOWN), 0.0); |
| Assertions.assertEquals(-1.23, Precision.round(-x, 2, RoundingMode.HALF_DOWN), 0.0); |
| Assertions.assertEquals(-1.235, Precision.round(-x, 3, RoundingMode.HALF_DOWN), 0.0); |
| Assertions.assertEquals(-1.2346, Precision.round(-x, 4, RoundingMode.HALF_DOWN), 0.0); |
| Assertions.assertEquals(1.234, Precision.round(1.2345, 3, RoundingMode.HALF_DOWN), 0.0); |
| Assertions.assertEquals(-1.234, Precision.round(-1.2345, 3, RoundingMode.HALF_DOWN), 0.0); |
| |
| Assertions.assertEquals(1.23, Precision.round(x, 2, RoundingMode.HALF_EVEN), 0.0); |
| Assertions.assertEquals(1.235, Precision.round(x, 3, RoundingMode.HALF_EVEN), 0.0); |
| Assertions.assertEquals(1.2346, Precision.round(x, 4, RoundingMode.HALF_EVEN), 0.0); |
| Assertions.assertEquals(-1.23, Precision.round(-x, 2, RoundingMode.HALF_EVEN), 0.0); |
| Assertions.assertEquals(-1.235, Precision.round(-x, 3, RoundingMode.HALF_EVEN), 0.0); |
| Assertions.assertEquals(-1.2346, Precision.round(-x, 4, RoundingMode.HALF_EVEN), 0.0); |
| Assertions.assertEquals(1.234, Precision.round(1.2345, 3, RoundingMode.HALF_EVEN), 0.0); |
| Assertions.assertEquals(-1.234, Precision.round(-1.2345, 3, RoundingMode.HALF_EVEN), 0.0); |
| Assertions.assertEquals(1.236, Precision.round(1.2355, 3, RoundingMode.HALF_EVEN), 0.0); |
| Assertions.assertEquals(-1.236, Precision.round(-1.2355, 3, RoundingMode.HALF_EVEN), 0.0); |
| |
| Assertions.assertEquals(1.23, Precision.round(x, 2, RoundingMode.HALF_UP), 0.0); |
| Assertions.assertEquals(1.235, Precision.round(x, 3, RoundingMode.HALF_UP), 0.0); |
| Assertions.assertEquals(1.2346, Precision.round(x, 4, RoundingMode.HALF_UP), 0.0); |
| Assertions.assertEquals(-1.23, Precision.round(-x, 2, RoundingMode.HALF_UP), 0.0); |
| Assertions.assertEquals(-1.235, Precision.round(-x, 3, RoundingMode.HALF_UP), 0.0); |
| Assertions.assertEquals(-1.2346, Precision.round(-x, 4, RoundingMode.HALF_UP), 0.0); |
| Assertions.assertEquals(1.235, Precision.round(1.2345, 3, RoundingMode.HALF_UP), 0.0); |
| Assertions.assertEquals(-1.235, Precision.round(-1.2345, 3, RoundingMode.HALF_UP), 0.0); |
| |
| Assertions.assertEquals(-1.23, Precision.round(-1.23, 2, RoundingMode.UNNECESSARY), 0.0); |
| Assertions.assertEquals(1.23, Precision.round(1.23, 2, RoundingMode.UNNECESSARY), 0.0); |
| |
| try { |
| Precision.round(1.234, 2, RoundingMode.UNNECESSARY); |
| Assertions.fail(); |
| } catch (ArithmeticException ex) { |
| // expected |
| } |
| |
| Assertions.assertEquals(1.24, Precision.round(x, 2, RoundingMode.UP), 0.0); |
| Assertions.assertEquals(1.235, Precision.round(x, 3, RoundingMode.UP), 0.0); |
| Assertions.assertEquals(1.2346, Precision.round(x, 4, RoundingMode.UP), 0.0); |
| Assertions.assertEquals(-1.24, Precision.round(-x, 2, RoundingMode.UP), 0.0); |
| Assertions.assertEquals(-1.235, Precision.round(-x, 3, RoundingMode.UP), 0.0); |
| Assertions.assertEquals(-1.2346, Precision.round(-x, 4, RoundingMode.UP), 0.0); |
| |
| // MATH-151 |
| Assertions.assertEquals(39.25, Precision.round(39.245, 2, RoundingMode.HALF_UP), 0.0); |
| |
| // special values |
| Assertions.assertEquals(Double.NaN, Precision.round(Double.NaN, 2), 0.0); |
| Assertions.assertEquals(0.0, Precision.round(0.0, 2), 0.0); |
| Assertions.assertEquals(Double.POSITIVE_INFINITY, Precision.round(Double.POSITIVE_INFINITY, 2), 0.0); |
| Assertions.assertEquals(Double.NEGATIVE_INFINITY, Precision.round(Double.NEGATIVE_INFINITY, 2), 0.0); |
| // comparison of positive and negative zero is not possible -> always equal thus do string comparison |
| Assertions.assertEquals("-0.0", Double.toString(Precision.round(-0.0, 0))); |
| Assertions.assertEquals("-0.0", Double.toString(Precision.round(-1e-10, 0))); |
| } |
| |
| @Test |
| void testRepresentableDelta() { |
| int nonRepresentableCount = 0; |
| final double x = 100; |
| final int numTrials = 10000; |
| for (int i = 0; i < numTrials; i++) { |
| final double originalDelta = Math.random(); |
| final double delta = Precision.representableDelta(x, originalDelta); |
| if (delta != originalDelta) { |
| ++nonRepresentableCount; |
| } |
| } |
| |
| Assertions.assertTrue(nonRepresentableCount / (double) numTrials > 0.9); |
| } |
| |
| @Test |
| void testIssue721() { |
| Assertions.assertEquals(-53, Math.getExponent(Precision.EPSILON)); |
| Assertions.assertEquals(-1022, Math.getExponent(Precision.SAFE_MIN)); |
| } |
| |
| @Test |
| void testMath475() { |
| final double a = 1.7976931348623182E16; |
| final double b = Math.nextUp(a); |
| |
| double diff = Math.abs(a - b); |
| // Because they are adjacent floating point numbers, "a" and "b" are |
| // considered equal even though the allowed error is smaller than |
| // their difference. |
| Assertions.assertTrue(Precision.equals(a, b, 0.5 * diff)); |
| |
| final double c = Math.nextUp(b); |
| diff = Math.abs(a - c); |
| // Because "a" and "c" are not adjacent, the tolerance is taken into |
| // account for assessing equality. |
| Assertions.assertTrue(Precision.equals(a, c, diff)); |
| Assertions.assertFalse(Precision.equals(a, c, Math.nextDown(1.0) * diff)); |
| } |
| |
| @Test |
| void testMath475Float() { |
| final float a = 1.7976931348623182E16f; |
| final float b = Math.nextUp(a); |
| |
| float diff = Math.abs(a - b); |
| // Because they are adjacent floating point numbers, "a" and "b" are |
| // considered equal even though the allowed error is smaller than |
| // their difference. |
| Assertions.assertTrue(Precision.equals(a, b, 0.5f * diff)); |
| |
| final float c = Math.nextUp(b); |
| diff = Math.abs(a - c); |
| // Because "a" and "c" are not adjacent, the tolerance is taken into |
| // account for assessing equality. |
| Assertions.assertTrue(Precision.equals(a, c, diff)); |
| Assertions.assertFalse(Precision.equals(a, c, Math.nextDown(1.0f) * diff)); |
| } |
| |
| @Test |
| void testMath843() { |
| final double afterEpsilon = Math.nextAfter(Precision.EPSILON, |
| Double.POSITIVE_INFINITY); |
| |
| // a) 1 + EPSILON is equal to 1. |
| Assertions.assertEquals(1, 1 + Precision.EPSILON); |
| |
| // b) 1 + "the number after EPSILON" is not equal to 1. |
| Assertions.assertNotEquals(1, 1 + afterEpsilon, 0.0); |
| } |
| |
| @Test |
| void testMath1127() { |
| Assertions.assertFalse(Precision.equals(2.0, -2.0, 1)); |
| Assertions.assertTrue(Precision.equals(0.0, -0.0, 0)); |
| Assertions.assertFalse(Precision.equals(2.0f, -2.0f, 1)); |
| Assertions.assertTrue(Precision.equals(0.0f, -0.0f, 0)); |
| } |
| } |