| /* |
| * 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.fraction; |
| |
| import org.junit.jupiter.api.Test; |
| import static org.junit.jupiter.api.Assertions.assertEquals; |
| import static org.junit.jupiter.api.Assertions.assertNotEquals; |
| import static org.junit.jupiter.api.Assertions.assertSame; |
| import static org.junit.jupiter.api.Assertions.assertThrows; |
| import static org.junit.jupiter.api.Assertions.assertTrue; |
| |
| import java.util.function.BiFunction; |
| import java.util.function.UnaryOperator; |
| |
| /** |
| * Test cases for the {@link Fraction} class. |
| * |
| * <p>This class is ported from commons lang to demonstrate interoperability of |
| * the Fraction class in numbers.</p> |
| */ |
| class CommonsLangPortedFractionTest { |
| |
| private static final int SKIP = 500; //53 |
| |
| //-------------------------------------------------------------------------- |
| @Test |
| void testConstants() { |
| assertEquals(0, Fraction.ZERO.getNumerator()); |
| assertEquals(1, Fraction.ZERO.getDenominator()); |
| |
| assertEquals(1, Fraction.ONE.getNumerator()); |
| assertEquals(1, Fraction.ONE.getDenominator()); |
| |
| /* |
| * All these constants need not be supported. |
| * Users can create whatever constants they require. |
| * The special constants ZERO and ONE are for the additive and multiplicative identity. |
| * |
| * assertEquals(1, Fraction.ONE_HALF.getNumerator()); |
| * assertEquals(2, Fraction.ONE_HALF.getDenominator()); |
| * |
| * assertEquals(1, Fraction.ONE_THIRD.getNumerator()); |
| * assertEquals(3, Fraction.ONE_THIRD.getDenominator()); |
| * |
| * assertEquals(2, Fraction.TWO_THIRDS.getNumerator()); |
| * assertEquals(3, Fraction.TWO_THIRDS.getDenominator()); |
| * |
| * assertEquals(1, Fraction.ONE_QUARTER.getNumerator()); |
| * assertEquals(4, Fraction.ONE_QUARTER.getDenominator()); |
| * |
| * assertEquals(1, Fraction.TWO_QUARTERS.getNumerator()); |
| * assertEquals(2, Fraction.TWO_QUARTERS.getDenominator()); |
| * |
| * assertEquals(3, Fraction.THREE_QUARTERS.getNumerator()); |
| * assertEquals(4, Fraction.THREE_QUARTERS.getDenominator()); |
| * |
| * assertEquals(1, Fraction.ONE_FIFTH.getNumerator()); |
| * assertEquals(5, Fraction.ONE_FIFTH.getDenominator()); |
| * |
| * assertEquals(2, Fraction.TWO_FIFTHS.getNumerator()); |
| * assertEquals(5, Fraction.TWO_FIFTHS.getDenominator()); |
| * |
| * assertEquals(3, Fraction.THREE_FIFTHS.getNumerator()); |
| * assertEquals(5, Fraction.THREE_FIFTHS.getDenominator()); |
| * |
| * assertEquals(4, Fraction.FOUR_FIFTHS.getNumerator()); |
| * assertEquals(5, Fraction.FOUR_FIFTHS.getDenominator()); |
| */ |
| } |
| |
| @Test |
| void testFactory_int_int() { |
| Fraction f = null; |
| |
| // zero |
| f = Fraction.of(0, 1); |
| assertEquals(0, f.getNumerator()); |
| assertEquals(1, f.getDenominator()); |
| |
| f = Fraction.of(0, 2); |
| assertEquals(0, f.getNumerator()); |
| assertEquals(1, f.getDenominator()); |
| |
| // normal |
| f = Fraction.of(1, 1); |
| assertEquals(1, f.getNumerator()); |
| assertEquals(1, f.getDenominator()); |
| |
| f = Fraction.of(2, 1); |
| assertEquals(2, f.getNumerator()); |
| assertEquals(1, f.getDenominator()); |
| |
| f = Fraction.of(23, 345); |
| assertEquals(1, f.getNumerator()); |
| assertEquals(15, f.getDenominator()); |
| |
| // improper |
| f = Fraction.of(22, 7); |
| assertEquals(22, f.getNumerator()); |
| assertEquals(7, f.getDenominator()); |
| |
| // negatives |
| f = Fraction.of(-6, 10); |
| assertEquals(-3, f.getNumerator()); |
| assertEquals(5, f.getDenominator()); |
| |
| f = Fraction.of(6, -10); |
| assertEquals(3, f.getNumerator()); |
| assertEquals(-5, f.getDenominator()); |
| |
| f = Fraction.of(-6, -10); |
| assertEquals(-3, f.getNumerator()); |
| assertEquals(-5, f.getDenominator()); |
| |
| // zero denominator |
| assertThrows(ArithmeticException.class, () -> Fraction.of(1, 0)); |
| assertThrows(ArithmeticException.class, () -> Fraction.of(2, 0)); |
| assertThrows(ArithmeticException.class, () -> Fraction.of(-3, 0)); |
| |
| // lang cannot represent the unsimplified fraction with MIN_VALUE as the denominator |
| // assertThrows(ArithmeticException.class, () -> Fraction.getFraction(4, Integer.MIN_VALUE)); |
| // assertThrows(ArithmeticException.class, () -> Fraction.getFraction(1, Integer.MIN_VALUE)); |
| // numbers will always simplify the fraction |
| f = Fraction.of(4, Integer.MIN_VALUE); |
| assertEquals(-1, f.signum()); |
| assertEquals(1, f.getNumerator()); |
| assertEquals(Integer.MIN_VALUE / 4, f.getDenominator()); |
| // numbers can use MIN_VALUE as the denominator |
| f = Fraction.of(1, Integer.MIN_VALUE); |
| assertEquals(-1, f.signum()); |
| assertEquals(1, f.getNumerator()); |
| assertEquals(Integer.MIN_VALUE, f.getDenominator()); |
| } |
| |
| /* |
| * Removed as not supported in numbers. |
| * |
| * @Test |
| * void testFactory_int_int_int() { |
| * Fraction f = null; |
| * |
| * // zero |
| * f = Fraction.of(0, 0, 2); |
| * assertEquals(0, f.getNumerator()); |
| * assertEquals(1, f.getDenominator()); |
| * |
| * f = Fraction.of(2, 0, 2); |
| * assertEquals(2, f.getNumerator()); |
| * assertEquals(1, f.getDenominator()); |
| * |
| * f = Fraction.of(0, 1, 2); |
| * assertEquals(1, f.getNumerator()); |
| * assertEquals(2, f.getDenominator()); |
| * |
| * // normal |
| * f = Fraction.of(1, 1, 2); |
| * assertEquals(3, f.getNumerator()); |
| * assertEquals(2, f.getDenominator()); |
| * |
| * // negatives |
| * assertThrows(ArithmeticException.class, () -> Fraction.of(1, -6, -10)); |
| * assertThrows(ArithmeticException.class, () -> Fraction.of(1, -6, -10)); |
| * assertThrows(ArithmeticException.class, () -> Fraction.of(1, -6, -10)); |
| * |
| * // negative whole |
| * f = Fraction.of(-1, 6, 10); |
| * assertEquals(-8, f.getNumerator()); |
| * assertEquals(5, f.getDenominator()); |
| * |
| * assertThrows(ArithmeticException.class, () -> Fraction.of(-1, -6, 10)); |
| * assertThrows(ArithmeticException.class, () -> Fraction.of(-1, 6, -10)); |
| * assertThrows(ArithmeticException.class, () -> Fraction.of(-1, -6, -10)); |
| * |
| * // zero denominator |
| * assertThrows(ArithmeticException.class, () -> Fraction.of(0, 1, 0)); |
| * assertThrows(ArithmeticException.class, () -> Fraction.of(1, 2, 0)); |
| * assertThrows(ArithmeticException.class, () -> Fraction.of(-1, -3, 0)); |
| * assertThrows(ArithmeticException.class, () -> Fraction.of(Integer.MAX_VALUE, 1, 2)); |
| * assertThrows(ArithmeticException.class, () -> Fraction.of(-Integer.MAX_VALUE, 1, 2)); |
| * |
| * // very large |
| * f = Fraction.of(-1, 0, Integer.MAX_VALUE); |
| * assertEquals(-1, f.getNumerator()); |
| * assertEquals(1, f.getDenominator()); |
| * |
| * // negative denominators not allowed in this constructor. |
| * assertThrows(ArithmeticException.class, () -> Fraction.of(0, 4, Integer.MIN_VALUE)); |
| * assertThrows(ArithmeticException.class, () -> Fraction.of(1, 1, Integer.MAX_VALUE)); |
| * assertThrows(ArithmeticException.class, () -> Fraction.of(-1, 2, Integer.MAX_VALUE)); |
| * } |
| */ |
| |
| @Test |
| void testReducedFactory_int_int() { |
| Fraction f = null; |
| |
| // zero |
| f = Fraction.of(0, 1); |
| assertEquals(0, f.getNumerator()); |
| assertEquals(1, f.getDenominator()); |
| |
| // normal |
| f = Fraction.of(1, 1); |
| assertEquals(1, f.getNumerator()); |
| assertEquals(1, f.getDenominator()); |
| |
| f = Fraction.of(2, 1); |
| assertEquals(2, f.getNumerator()); |
| assertEquals(1, f.getDenominator()); |
| |
| // improper |
| f = Fraction.of(22, 7); |
| assertEquals(22, f.getNumerator()); |
| assertEquals(7, f.getDenominator()); |
| |
| // negatives |
| f = Fraction.of(-6, 10); |
| assertEquals(-3, f.getNumerator()); |
| assertEquals(5, f.getDenominator()); |
| |
| f = Fraction.of(6, -10); |
| assertEquals(3, f.getNumerator()); |
| assertEquals(-5, f.getDenominator()); |
| |
| f = Fraction.of(-6, -10); |
| assertEquals(-3, f.getNumerator()); |
| assertEquals(-5, f.getDenominator()); |
| |
| // zero denominator |
| assertThrows(ArithmeticException.class, () -> Fraction.of(1, 0)); |
| assertThrows(ArithmeticException.class, () -> Fraction.of(2, 0)); |
| assertThrows(ArithmeticException.class, () -> Fraction.of(-3, 0)); |
| |
| // reduced |
| f = Fraction.of(0, 2); |
| assertEquals(0, f.getNumerator()); |
| assertEquals(1, f.getDenominator()); |
| |
| f = Fraction.of(2, 2); |
| assertEquals(1, f.getNumerator()); |
| assertEquals(1, f.getDenominator()); |
| |
| f = Fraction.of(2, 4); |
| assertEquals(1, f.getNumerator()); |
| assertEquals(2, f.getDenominator()); |
| |
| f = Fraction.of(15, 10); |
| assertEquals(3, f.getNumerator()); |
| assertEquals(2, f.getDenominator()); |
| |
| f = Fraction.of(121, 22); |
| assertEquals(11, f.getNumerator()); |
| assertEquals(2, f.getDenominator()); |
| |
| // Extreme values |
| // OK, can reduce before negating |
| f = Fraction.of(-2, Integer.MIN_VALUE); |
| assertEquals(-1, f.getNumerator()); |
| assertEquals(Integer.MIN_VALUE / 2, f.getDenominator()); |
| |
| // lang requires the sign to be in the numerator so this would throw. |
| // assertThrows(ArithmeticException.class, () -> Fraction.getReducedFraction(-7, Integer.MIN_VALUE)); |
| // numbers allows the sign to be in the denominator so this does not throw. |
| f = Fraction.of(-7, Integer.MIN_VALUE); |
| assertEquals(1, f.signum()); |
| assertEquals(-7, f.getNumerator()); |
| assertEquals(Integer.MIN_VALUE, f.getDenominator()); |
| |
| // LANG-662 |
| f = Fraction.of(Integer.MIN_VALUE, 2); |
| assertEquals(Integer.MIN_VALUE / 2, f.getNumerator()); |
| assertEquals(1, f.getDenominator()); |
| } |
| |
| @Test |
| void testFactory_double() { |
| assertThrows(IllegalArgumentException.class, () -> Fraction.from(Double.NaN)); |
| assertThrows(IllegalArgumentException.class, () -> Fraction.from(Double.POSITIVE_INFINITY)); |
| assertThrows(IllegalArgumentException.class, () -> Fraction.from(Double.NEGATIVE_INFINITY)); |
| Fraction.from((double) Integer.MAX_VALUE + 1); |
| |
| // zero |
| Fraction f = Fraction.from(0.0d); |
| assertEquals(0, f.getNumerator()); |
| assertEquals(1, f.getDenominator()); |
| |
| // one |
| f = Fraction.from(1.0d); |
| assertEquals(1, f.getNumerator()); |
| assertEquals(1, f.getDenominator()); |
| |
| // one half |
| f = Fraction.from(0.5d); |
| assertEquals(1, f.getNumerator()); |
| assertEquals(2, f.getDenominator()); |
| |
| // negative |
| f = Fraction.from(-0.875d); |
| assertEquals(-7, f.getNumerator()); |
| assertEquals(8, f.getDenominator()); |
| |
| // over 1 |
| f = Fraction.from(1.25d); |
| assertEquals(5, f.getNumerator()); |
| assertEquals(4, f.getDenominator()); |
| |
| // two thirds |
| f = Fraction.from(0.66666d); |
| assertEquals(2, f.getNumerator()); |
| assertEquals(3, f.getDenominator()); |
| |
| // small |
| f = Fraction.from(1.0d / 10001d); |
| assertEquals(1, f.getNumerator()); |
| assertEquals(10001, f.getDenominator()); |
| |
| // normal |
| Fraction f2 = null; |
| for (int i = 1; i <= 100; i++) { // denominator |
| for (int j = 1; j <= i; j++) { // numerator |
| f = Fraction.from((double) j / (double) i); |
| |
| f2 = Fraction.of(j, i); |
| assertEquals(f2.getNumerator(), f.getNumerator()); |
| assertEquals(f2.getDenominator(), f.getDenominator()); |
| } |
| } |
| // save time by skipping some tests! ( |
| for (int i = 1001; i <= 10000; i += SKIP) { // denominator |
| for (int j = 1; j <= i; j++) { // numerator |
| f = Fraction.from((double) j / (double) i, 1e-8, 100); |
| f2 = Fraction.of(j, i); |
| assertEquals(f2.getNumerator(), f.getNumerator()); |
| assertEquals(f2.getDenominator(), f.getDenominator()); |
| } |
| } |
| } |
| |
| /* |
| * Removed as not supported in numbers. |
| * |
| * @Test |
| * void testFactory_String() { |
| * assertThrows(NullPointerException.class, () -> Fraction.from(null)); |
| * } |
| * |
| * |
| * @Test |
| * void testFactory_String_double() { |
| * Fraction f = null; |
| * |
| * f = Fraction.from("0.0"); |
| * assertEquals(0, f.getNumerator()); |
| * assertEquals(1, f.getDenominator()); |
| * |
| * f = Fraction.from("0.2"); |
| * assertEquals(1, f.getNumerator()); |
| * assertEquals(5, f.getDenominator()); |
| * |
| * f = Fraction.from("0.5"); |
| * assertEquals(1, f.getNumerator()); |
| * assertEquals(2, f.getDenominator()); |
| * |
| * f = Fraction.from("0.66666"); |
| * assertEquals(2, f.getNumerator()); |
| * assertEquals(3, f.getDenominator()); |
| * |
| * assertThrows(NumberFormatException.class, () -> Fraction.from("2.3R")); |
| * assertThrows(NumberFormatException.class, () -> Fraction.from("2147483648")); // too big |
| * assertThrows(NumberFormatException.class, () -> Fraction.from(".")); |
| * } |
| * |
| * @Test |
| * void testFactory_String_proper() { |
| * Fraction f = null; |
| * |
| * f = Fraction.from("0 0/1"); |
| * assertEquals(0, f.getNumerator()); |
| * assertEquals(1, f.getDenominator()); |
| * |
| * f = Fraction.from("1 1/5"); |
| * assertEquals(6, f.getNumerator()); |
| * assertEquals(5, f.getDenominator()); |
| * |
| * f = Fraction.from("7 1/2"); |
| * assertEquals(15, f.getNumerator()); |
| * assertEquals(2, f.getDenominator()); |
| * |
| * f = Fraction.from("1 2/4"); |
| * assertEquals(3, f.getNumerator()); |
| * assertEquals(2, f.getDenominator()); |
| * |
| * f = Fraction.from("-7 1/2"); |
| * assertEquals(-15, f.getNumerator()); |
| * assertEquals(2, f.getDenominator()); |
| * |
| * f = Fraction.from("-1 2/4"); |
| * assertEquals(-3, f.getNumerator()); |
| * assertEquals(2, f.getDenominator()); |
| * |
| * assertThrows(NumberFormatException.class, () -> Fraction.from("2 3")); |
| * assertThrows(NumberFormatException.class, () -> Fraction.from("a 3")); |
| * assertThrows(NumberFormatException.class, () -> Fraction.from("2 b/4")); |
| * assertThrows(NumberFormatException.class, () -> Fraction.from("2 ")); |
| * assertThrows(NumberFormatException.class, () -> Fraction.from(" 3")); |
| * assertThrows(NumberFormatException.class, () -> Fraction.from(" ")); |
| * } |
| * |
| * @Test |
| * void testFactory_String_improper() { |
| * Fraction f = null; |
| * |
| * f = Fraction.from("0/1"); |
| * assertEquals(0, f.getNumerator()); |
| * assertEquals(1, f.getDenominator()); |
| * |
| * f = Fraction.from("1/5"); |
| * assertEquals(1, f.getNumerator()); |
| * assertEquals(5, f.getDenominator()); |
| * |
| * f = Fraction.from("1/2"); |
| * assertEquals(1, f.getNumerator()); |
| * assertEquals(2, f.getDenominator()); |
| * |
| * f = Fraction.from("2/3"); |
| * assertEquals(2, f.getNumerator()); |
| * assertEquals(3, f.getDenominator()); |
| * |
| * f = Fraction.from("7/3"); |
| * assertEquals(7, f.getNumerator()); |
| * assertEquals(3, f.getDenominator()); |
| * |
| * f = Fraction.from("2/4"); |
| * assertEquals(1, f.getNumerator()); |
| * assertEquals(2, f.getDenominator()); |
| * |
| * assertThrows(NumberFormatException.class, () -> Fraction.from("2/d")); |
| * assertThrows(NumberFormatException.class, () -> Fraction.from("2e/3")); |
| * assertThrows(NumberFormatException.class, () -> Fraction.from("2/")); |
| * assertThrows(NumberFormatException.class, () -> Fraction.from("/")); |
| * } |
| * |
| * @Test |
| * void testGets() { |
| * Fraction f = null; |
| * |
| * f = Fraction.of(3, 5, 6); |
| * assertEquals(23, f.getNumerator()); |
| * assertEquals(3, f.getProperWhole()); |
| * assertEquals(5, f.getProperNumerator()); |
| * assertEquals(6, f.getDenominator()); |
| * |
| * f = Fraction.of(-3, 5, 6); |
| * assertEquals(-23, f.getNumerator()); |
| * assertEquals(-3, f.getProperWhole()); |
| * assertEquals(5, f.getProperNumerator()); |
| * assertEquals(6, f.getDenominator()); |
| * |
| * f = Fraction.of(Integer.MIN_VALUE, 0, 1); |
| * assertEquals(Integer.MIN_VALUE, f.getNumerator()); |
| * assertEquals(Integer.MIN_VALUE, f.getProperWhole()); |
| * assertEquals(0, f.getProperNumerator()); |
| * assertEquals(1, f.getDenominator()); |
| * } |
| * |
| * @Test |
| * void testConversions() { |
| * Fraction f = null; |
| * |
| * f = Fraction.of(3, 7, 8); |
| * assertEquals(3, f.intValue()); |
| * assertEquals(3L, f.longValue()); |
| * assertEquals(3.875f, f.floatValue(), 0.00001f); |
| * assertEquals(3.875d, f.doubleValue(), 0.00001d); |
| * } |
| * |
| * @Test |
| * void testReduce() { |
| * Fraction f = null; |
| * |
| * f = Fraction.of(50, 75); |
| * Fraction result = f.reduce(); |
| * assertEquals(2, result.getNumerator()); |
| * assertEquals(3, result.getDenominator()); |
| * |
| * f = Fraction.of(-2, -3); |
| * result = f.reduce(); |
| * assertEquals(2, result.getNumerator()); |
| * assertEquals(3, result.getDenominator()); |
| * |
| * f = Fraction.of(2, -3); |
| * result = f.reduce(); |
| * assertEquals(-2, result.getNumerator()); |
| * assertEquals(3, result.getDenominator()); |
| * |
| * f = Fraction.of(-2, 3); |
| * result = f.reduce(); |
| * assertEquals(-2, result.getNumerator()); |
| * assertEquals(3, result.getDenominator()); |
| * assertSame(f, result); |
| * |
| * f = Fraction.of(2, 3); |
| * result = f.reduce(); |
| * assertEquals(2, result.getNumerator()); |
| * assertEquals(3, result.getDenominator()); |
| * assertSame(f, result); |
| * |
| * f = Fraction.of(0, 1); |
| * result = f.reduce(); |
| * assertEquals(0, result.getNumerator()); |
| * assertEquals(1, result.getDenominator()); |
| * assertSame(f, result); |
| * |
| * f = Fraction.of(0, 100); |
| * result = f.reduce(); |
| * assertEquals(0, result.getNumerator()); |
| * assertEquals(1, result.getDenominator()); |
| * assertSame(result, Fraction.ZERO); |
| * |
| * f = Fraction.of(Integer.MIN_VALUE, 2); |
| * result = f.reduce(); |
| * assertEquals(Integer.MIN_VALUE / 2, result.getNumerator()); |
| * assertEquals(1, result.getDenominator()); |
| * } |
| * |
| * @Test |
| * void testreciprocal() { |
| * Fraction f = null; |
| * |
| * f = Fraction.of(50, 75); |
| * f = f.reciprocal(); |
| * assertEquals(3, f.getNumerator()); |
| * assertEquals(2, f.getDenominator()); |
| * |
| * f = Fraction.of(4, 3); |
| * f = f.reciprocal(); |
| * assertEquals(3, f.getNumerator()); |
| * assertEquals(4, f.getDenominator()); |
| * |
| * f = Fraction.of(-15, 47); |
| * f = f.reciprocal(); |
| * assertEquals(47, f.getNumerator()); |
| * assertEquals(-15, f.getDenominator()); |
| * |
| * assertThrows(ArithmeticException.class, () -> Fraction.of(0, 3).reciprocal()); |
| * Fraction.of(Integer.MIN_VALUE, 1).reciprocal(); |
| * |
| * f = Fraction.of(Integer.MAX_VALUE, 1); |
| * f = f.reciprocal(); |
| * assertEquals(1, f.getNumerator()); |
| * assertEquals(Integer.MAX_VALUE, f.getDenominator()); |
| * } |
| */ |
| |
| @Test |
| void testNegate() { |
| Fraction f = null; |
| |
| f = Fraction.of(50, 75); |
| f = f.negate(); |
| assertEquals(-2, f.getNumerator()); |
| assertEquals(3, f.getDenominator()); |
| |
| f = Fraction.of(-50, 75); |
| f = f.negate(); |
| assertEquals(2, f.getNumerator()); |
| assertEquals(3, f.getDenominator()); |
| |
| // large values |
| f = Fraction.of(Integer.MAX_VALUE - 1, Integer.MAX_VALUE); |
| f = f.negate(); |
| assertEquals(Integer.MIN_VALUE + 2, f.getNumerator()); |
| assertEquals(Integer.MAX_VALUE, f.getDenominator()); |
| |
| // lang requires the sign in the numerator and so cannot negate MIN_VALUE as the numerator |
| // assertThrows(ArithmeticException.class, () -> Fraction.getFraction(Integer.MIN_VALUE, 1).negate()); |
| // numbers allows the sign in the numerator or denominator |
| f = Fraction.of(Integer.MIN_VALUE, 1).negate(); |
| assertEquals(1, f.signum()); |
| assertEquals(Integer.MIN_VALUE, f.getNumerator()); |
| assertEquals(-1, f.getDenominator()); |
| } |
| |
| @Test |
| void testAbs() { |
| Fraction f = null; |
| |
| f = Fraction.of(50, 75); |
| f = f.abs(); |
| assertEquals(2, f.getNumerator()); |
| assertEquals(3, f.getDenominator()); |
| |
| f = Fraction.of(-50, 75); |
| f = f.abs(); |
| assertEquals(2, f.getNumerator()); |
| assertEquals(3, f.getDenominator()); |
| |
| f = Fraction.of(Integer.MAX_VALUE, 1); |
| f = f.abs(); |
| assertEquals(Integer.MAX_VALUE, f.getNumerator()); |
| assertEquals(1, f.getDenominator()); |
| |
| f = Fraction.of(Integer.MAX_VALUE, -1); |
| f = f.abs(); |
| assertEquals(-Integer.MAX_VALUE, f.getNumerator()); |
| assertEquals(-1, f.getDenominator()); |
| |
| // lang requires the sign in the numerator and so cannot compute the absolute with MIN_VALUE as the numerator |
| // assertThrows(ArithmeticException.class, () -> Fraction.getFraction(Integer.MIN_VALUE, 1).abs()); |
| // numbers allows the sign in the numerator or denominator |
| f = Fraction.of(Integer.MIN_VALUE, 1).abs(); |
| assertEquals(1, f.signum()); |
| assertEquals(Integer.MIN_VALUE, f.getNumerator()); |
| assertEquals(-1, f.getDenominator()); |
| } |
| |
| @Test |
| void testPow() { |
| Fraction f = null; |
| |
| f = Fraction.of(3, 5); |
| assertEquals(Fraction.ONE, f.pow(0)); |
| |
| f = Fraction.of(3, 5); |
| assertEquals(f, f.pow(1)); |
| assertEquals(f, f.pow(1)); |
| |
| f = Fraction.of(3, 5); |
| f = f.pow(2); |
| assertEquals(9, f.getNumerator()); |
| assertEquals(25, f.getDenominator()); |
| |
| f = Fraction.of(3, 5); |
| f = f.pow(3); |
| assertEquals(27, f.getNumerator()); |
| assertEquals(125, f.getDenominator()); |
| |
| f = Fraction.of(3, 5); |
| f = f.pow(-1); |
| assertEquals(5, f.getNumerator()); |
| assertEquals(3, f.getDenominator()); |
| |
| f = Fraction.of(3, 5); |
| f = f.pow(-2); |
| assertEquals(25, f.getNumerator()); |
| assertEquals(9, f.getDenominator()); |
| |
| // check unreduced fractions stay that way. |
| f = Fraction.of(6, 10); |
| assertEquals(Fraction.ONE, f.pow(0)); |
| |
| f = Fraction.of(6, 10); |
| assertEquals(f, f.pow(1)); |
| assertEquals(f.pow(1), Fraction.of(3, 5)); |
| |
| f = Fraction.of(6, 10); |
| f = f.pow(2); |
| assertEquals(9, f.getNumerator()); |
| assertEquals(25, f.getDenominator()); |
| |
| f = Fraction.of(6, 10); |
| f = f.pow(3); |
| assertEquals(27, f.getNumerator()); |
| assertEquals(125, f.getDenominator()); |
| |
| f = Fraction.of(6, 10); |
| f = f.pow(-1); |
| assertEquals(5, f.getNumerator()); |
| assertEquals(3, f.getDenominator()); |
| |
| f = Fraction.of(6, 10); |
| f = f.pow(-2); |
| assertEquals(25, f.getNumerator()); |
| assertEquals(9, f.getDenominator()); |
| |
| // zero to any positive power is still zero. |
| f = Fraction.of(0, 1231); |
| f = f.pow(1); |
| assertEquals(0, f.compareTo(Fraction.ZERO)); |
| assertEquals(0, f.getNumerator()); |
| assertEquals(1, f.getDenominator()); |
| f = f.pow(2); |
| assertEquals(0, f.compareTo(Fraction.ZERO)); |
| assertEquals(0, f.getNumerator()); |
| assertEquals(1, f.getDenominator()); |
| |
| // zero to negative powers should throw an exception |
| final Fraction fr = f; |
| assertThrows(ArithmeticException.class, () -> fr.pow(-1)); |
| assertThrows(ArithmeticException.class, () -> fr.pow(Integer.MIN_VALUE)); |
| |
| // one to any power is still one. |
| f = Fraction.of(1, 1); |
| f = f.pow(0); |
| assertEquals(Fraction.ONE, f); |
| f = f.pow(1); |
| assertEquals(Fraction.ONE, f); |
| f = f.pow(-1); |
| assertEquals(Fraction.ONE, f); |
| f = f.pow(Integer.MAX_VALUE); |
| assertEquals(Fraction.ONE, f); |
| f = f.pow(Integer.MIN_VALUE); |
| assertEquals(Fraction.ONE, f); |
| |
| assertOperationThrows(ArithmeticException.class, Fraction.of(Integer.MAX_VALUE, 1), a -> a.pow(2)); |
| |
| // Numerator growing too negative during the pow operation. |
| assertOperationThrows(ArithmeticException.class, Fraction.of(Integer.MIN_VALUE, 1), a -> a.pow(3)); |
| |
| assertOperationThrows(ArithmeticException.class, Fraction.of(65536, 1), a -> a.pow(2)); |
| } |
| |
| @Test |
| void testAdd() { |
| Fraction f = null; |
| Fraction f1 = null; |
| Fraction f2 = null; |
| |
| f1 = Fraction.of(3, 5); |
| f2 = Fraction.of(1, 5); |
| f = f1.add(f2); |
| assertEquals(4, f.getNumerator()); |
| assertEquals(5, f.getDenominator()); |
| |
| f1 = Fraction.of(3, 5); |
| f2 = Fraction.of(2, 5); |
| f = f1.add(f2); |
| assertEquals(1, f.getNumerator()); |
| assertEquals(1, f.getDenominator()); |
| |
| f1 = Fraction.of(3, 5); |
| f2 = Fraction.of(3, 5); |
| f = f1.add(f2); |
| assertEquals(6, f.getNumerator()); |
| assertEquals(5, f.getDenominator()); |
| |
| f1 = Fraction.of(3, 5); |
| f2 = Fraction.of(-4, 5); |
| f = f1.add(f2); |
| assertEquals(-1, f.getNumerator()); |
| assertEquals(5, f.getDenominator()); |
| |
| f1 = Fraction.of(Integer.MAX_VALUE - 1, 1); |
| f2 = Fraction.ONE; |
| f = f1.add(f2); |
| assertEquals(Integer.MAX_VALUE, f.getNumerator()); |
| assertEquals(1, f.getDenominator()); |
| |
| f1 = Fraction.of(3, 5); |
| f2 = Fraction.of(1, 2); |
| f = f1.add(f2); |
| assertEquals(11, f.getNumerator()); |
| assertEquals(10, f.getDenominator()); |
| |
| f1 = Fraction.of(3, 8); |
| f2 = Fraction.of(1, 6); |
| f = f1.add(f2); |
| assertEquals(13, f.getNumerator()); |
| assertEquals(24, f.getDenominator()); |
| |
| f1 = Fraction.of(0, 5); |
| f2 = Fraction.of(1, 5); |
| f = f1.add(f2); |
| assertSame(f2, f); |
| f = f2.add(f1); |
| assertSame(f2, f); |
| |
| f1 = Fraction.of(-1, 13 * 13 * 2 * 2); |
| f2 = Fraction.of(-2, 13 * 17 * 2); |
| final Fraction fr = f1.add(f2); |
| assertEquals(13 * 13 * 17 * 2 * 2, fr.getDenominator()); |
| assertEquals(-17 - 2 * 13 * 2, fr.getNumerator()); |
| |
| assertThrows(NullPointerException.class, () -> fr.add(null)); |
| |
| // if this fraction is added naively, it will overflow. |
| // check that it doesn't. |
| f1 = Fraction.of(1, 32768 * 3); |
| f2 = Fraction.of(1, 59049); |
| f = f1.add(f2); |
| assertEquals(52451, f.getNumerator()); |
| assertEquals(1934917632, f.getDenominator()); |
| |
| f1 = Fraction.of(Integer.MIN_VALUE, 3); |
| f2 = Fraction.of(1, 3); |
| f = f1.add(f2); |
| assertEquals(Integer.MIN_VALUE + 1, f.getNumerator()); |
| assertEquals(3, f.getDenominator()); |
| |
| f1 = Fraction.of(Integer.MAX_VALUE - 1, 1); |
| f2 = Fraction.ONE; |
| f = f1.add(f2); |
| assertEquals(Integer.MAX_VALUE, f.getNumerator()); |
| assertEquals(1, f.getDenominator()); |
| |
| final Fraction overflower = f; |
| assertThrows(ArithmeticException.class, () -> overflower.add(Fraction.ONE)); // should overflow |
| |
| // denominator should not be a multiple of 2 or 3 to trigger overflow |
| assertOperationThrows(ArithmeticException.class, Fraction.of(Integer.MIN_VALUE, 5), Fraction.of(-1, 5), Fraction::add); |
| |
| final Fraction maxValue = Fraction.of(-Integer.MAX_VALUE, 1); |
| assertThrows(ArithmeticException.class, () -> maxValue.add(maxValue)); |
| |
| final Fraction negativeMaxValue = Fraction.of(-Integer.MAX_VALUE, 1); |
| assertThrows(ArithmeticException.class, () -> negativeMaxValue.add(negativeMaxValue)); |
| |
| final Fraction f3 = Fraction.of(3, 327680); |
| final Fraction f4 = Fraction.of(2, 59049); |
| assertThrows(ArithmeticException.class, () -> f3.add(f4)); // should overflow |
| } |
| |
| @Test |
| void testSubtract() { |
| Fraction f = null; |
| Fraction f1 = null; |
| Fraction f2 = null; |
| |
| f1 = Fraction.of(3, 5); |
| f2 = Fraction.of(1, 5); |
| f = f1.subtract(f2); |
| assertEquals(2, f.getNumerator()); |
| assertEquals(5, f.getDenominator()); |
| |
| f1 = Fraction.of(7, 5); |
| f2 = Fraction.of(2, 5); |
| f = f1.subtract(f2); |
| assertEquals(1, f.getNumerator()); |
| assertEquals(1, f.getDenominator()); |
| |
| f1 = Fraction.of(3, 5); |
| f2 = Fraction.of(3, 5); |
| f = f1.subtract(f2); |
| assertEquals(0, f.getNumerator()); |
| assertEquals(1, f.getDenominator()); |
| |
| f1 = Fraction.of(3, 5); |
| f2 = Fraction.of(-4, 5); |
| f = f1.subtract(f2); |
| assertEquals(7, f.getNumerator()); |
| assertEquals(5, f.getDenominator()); |
| |
| f1 = Fraction.of(0, 5); |
| f2 = Fraction.of(4, 5); |
| f = f1.subtract(f2); |
| assertEquals(-4, f.getNumerator()); |
| assertEquals(5, f.getDenominator()); |
| |
| f1 = Fraction.of(0, 5); |
| f2 = Fraction.of(-4, 5); |
| f = f1.subtract(f2); |
| assertEquals(4, f.getNumerator()); |
| assertEquals(5, f.getDenominator()); |
| |
| f1 = Fraction.of(3, 5); |
| f2 = Fraction.of(1, 2); |
| f = f1.subtract(f2); |
| assertEquals(1, f.getNumerator()); |
| assertEquals(10, f.getDenominator()); |
| |
| f1 = Fraction.of(0, 5); |
| f2 = Fraction.of(1, 5); |
| f = f2.subtract(f1); |
| assertSame(f2, f); |
| |
| final Fraction fr = f; |
| assertThrows(NullPointerException.class, () -> fr.subtract(null)); |
| |
| // if this fraction is subtracted naively, it will overflow. |
| // check that it doesn't. |
| f1 = Fraction.of(1, 32768 * 3); |
| f2 = Fraction.of(1, 59049); |
| f = f1.subtract(f2); |
| assertEquals(-13085, f.getNumerator()); |
| assertEquals(1934917632, f.getDenominator()); |
| |
| f1 = Fraction.of(Integer.MIN_VALUE, 3); |
| f2 = Fraction.of(1, 3).negate(); |
| f = f1.subtract(f2); |
| assertEquals(Integer.MIN_VALUE + 1, f.getNumerator()); |
| assertEquals(3, f.getDenominator()); |
| |
| f1 = Fraction.of(Integer.MAX_VALUE, 1); |
| f2 = Fraction.ONE; |
| f = f1.subtract(f2); |
| assertEquals(Integer.MAX_VALUE - 1, f.getNumerator()); |
| assertEquals(1, f.getDenominator()); |
| |
| // Should overflow |
| assertOperationThrows(ArithmeticException.class, Fraction.of(1, Integer.MAX_VALUE), Fraction.of(1, Integer.MAX_VALUE - 1), Fraction::subtract); |
| f = f1.subtract(f2); |
| |
| // denominator should not be a multiple of 2 or 3 to trigger overflow |
| assertOperationThrows(ArithmeticException.class, Fraction.of(Integer.MIN_VALUE, 5), Fraction.of(1, 5), Fraction::subtract); |
| |
| assertOperationThrows(ArithmeticException.class, Fraction.of(Integer.MIN_VALUE, 1), Fraction.ONE, Fraction::subtract); |
| |
| assertOperationThrows(ArithmeticException.class, Fraction.of(Integer.MAX_VALUE, 1), Fraction.ONE.negate(), Fraction::subtract); |
| |
| // Should overflow |
| assertOperationThrows(ArithmeticException.class, Fraction.of(3, 327680), Fraction.of(2, 59049), Fraction::subtract); |
| } |
| |
| @Test |
| void testMultiply() { |
| Fraction f = null; |
| Fraction f1 = null; |
| Fraction f2 = null; |
| |
| f1 = Fraction.of(3, 5); |
| f2 = Fraction.of(2, 5); |
| f = f1.multiply(f2); |
| assertEquals(6, f.getNumerator()); |
| assertEquals(25, f.getDenominator()); |
| |
| f1 = Fraction.of(6, 10); |
| f2 = Fraction.of(6, 10); |
| f = f1.multiply(f2); |
| assertEquals(9, f.getNumerator()); |
| assertEquals(25, f.getDenominator()); |
| f = f.multiply(f2); |
| assertEquals(27, f.getNumerator()); |
| assertEquals(125, f.getDenominator()); |
| |
| f1 = Fraction.of(3, 5); |
| f2 = Fraction.of(-2, 5); |
| f = f1.multiply(f2); |
| assertEquals(-6, f.getNumerator()); |
| assertEquals(25, f.getDenominator()); |
| |
| f1 = Fraction.of(-3, 5); |
| f2 = Fraction.of(-2, 5); |
| f = f1.multiply(f2); |
| assertEquals(6, f.getNumerator()); |
| assertEquals(25, f.getDenominator()); |
| |
| |
| f1 = Fraction.of(0, 5); |
| f2 = Fraction.of(2, 7); |
| f = f1.multiply(f2); |
| assertSame(Fraction.ZERO, f); |
| |
| f1 = Fraction.of(2, 7); |
| f2 = Fraction.ONE; |
| f = f1.multiply(f2); |
| assertEquals(2, f.getNumerator()); |
| assertEquals(7, f.getDenominator()); |
| |
| f1 = Fraction.of(Integer.MAX_VALUE, 1); |
| f2 = Fraction.of(Integer.MIN_VALUE, Integer.MAX_VALUE); |
| f = f1.multiply(f2); |
| assertEquals(Integer.MIN_VALUE, f.getNumerator()); |
| assertEquals(1, f.getDenominator()); |
| |
| final Fraction fr = f; |
| assertThrows(NullPointerException.class, () -> fr.multiply(null)); |
| |
| final Fraction fr1 = Fraction.of(1, Integer.MAX_VALUE); |
| assertThrows(ArithmeticException.class, () -> fr1.multiply(fr1)); |
| |
| final Fraction fr2 = Fraction.of(1, -Integer.MAX_VALUE); |
| assertThrows(ArithmeticException.class, () -> fr2.multiply(fr2)); |
| } |
| |
| @Test |
| void testDivide() { |
| Fraction f = null; |
| Fraction f1 = null; |
| Fraction f2 = null; |
| |
| f1 = Fraction.of(3, 5); |
| f2 = Fraction.of(2, 5); |
| f = f1.divide(f2); |
| assertEquals(3, f.getNumerator()); |
| assertEquals(2, f.getDenominator()); |
| |
| assertOperationThrows(ArithmeticException.class, Fraction.of(3, 5), Fraction.ZERO, Fraction::divide); |
| |
| f1 = Fraction.of(0, 5); |
| f2 = Fraction.of(2, 7); |
| f = f1.divide(f2); |
| assertSame(Fraction.ZERO, f); |
| |
| f1 = Fraction.of(2, 7); |
| f2 = Fraction.ONE; |
| f = f1.divide(f2); |
| assertEquals(2, f.getNumerator()); |
| assertEquals(7, f.getDenominator()); |
| |
| f1 = Fraction.of(1, Integer.MAX_VALUE); |
| f = f1.divide(f1); |
| assertEquals(1, f.getNumerator()); |
| assertEquals(1, f.getDenominator()); |
| |
| f1 = Fraction.of(Integer.MIN_VALUE, Integer.MAX_VALUE); |
| f2 = Fraction.of(1, Integer.MAX_VALUE); |
| final Fraction fr = f1.divide(f2); |
| assertEquals(Integer.MIN_VALUE, fr.getNumerator()); |
| assertEquals(1, fr.getDenominator()); |
| |
| assertThrows(NullPointerException.class, () -> fr.divide(null)); |
| |
| final Fraction smallest = Fraction.of(1, Integer.MAX_VALUE); |
| final Fraction smallestReciprocal = smallest.reciprocal(); |
| assertThrows(ArithmeticException.class, () -> smallest.divide(smallestReciprocal)); // Should overflow |
| |
| final Fraction negative = Fraction.of(1, -Integer.MAX_VALUE); |
| final Fraction negativeReciprocal = negative.reciprocal(); |
| assertThrows(ArithmeticException.class, () -> negative.divide(negativeReciprocal)); // Should overflow |
| } |
| |
| @Test |
| void testEquals() { |
| Fraction f1 = null; |
| Fraction f2 = null; |
| |
| f1 = Fraction.of(3, 5); |
| assertNotEquals(null, f1); |
| assertNotEquals(f1, new Object()); |
| assertNotEquals(f1, Integer.valueOf(6)); |
| |
| f1 = Fraction.of(3, 5); |
| f2 = Fraction.of(2, 5); |
| assertNotEquals(f1, f2); |
| assertEquals(f1, f1); |
| assertEquals(f2, f2); |
| |
| f2 = Fraction.of(3, 5); |
| assertEquals(f1, f2); |
| |
| f2 = Fraction.of(6, 10); |
| assertEquals(f1, f2); |
| } |
| |
| @Test |
| void testHashCode() { |
| final Fraction f1 = Fraction.of(3, 5); |
| Fraction f2 = Fraction.of(3, 5); |
| |
| assertEquals(f1.hashCode(), f2.hashCode()); |
| |
| f2 = Fraction.of(2, 5); |
| assertNotEquals(f1.hashCode(), f2.hashCode()); |
| |
| f2 = Fraction.of(6, 10); |
| assertEquals(f1.hashCode(), f2.hashCode()); |
| } |
| |
| @Test |
| void testCompareTo() { |
| Fraction f1 = null; |
| Fraction f2 = null; |
| |
| f1 = Fraction.of(3, 5); |
| assertEquals(0, f1.compareTo(f1)); |
| |
| final Fraction fr = f1; |
| assertThrows(NullPointerException.class, () -> fr.compareTo(null)); |
| |
| f2 = Fraction.of(2, 5); |
| assertTrue(f1.compareTo(f2) > 0); |
| assertEquals(0, f2.compareTo(f2)); |
| |
| f2 = Fraction.of(4, 5); |
| assertTrue(f1.compareTo(f2) < 0); |
| assertEquals(0, f2.compareTo(f2)); |
| |
| f2 = Fraction.of(3, 5); |
| assertEquals(0, f1.compareTo(f2)); |
| assertEquals(0, f2.compareTo(f2)); |
| |
| f2 = Fraction.of(6, 10); |
| assertEquals(0, f1.compareTo(f2)); |
| assertEquals(0, f2.compareTo(f2)); |
| |
| /* |
| * Removed as not supported in numbers. |
| * |
| * f2 = Fraction.of(-1, 1, Integer.MAX_VALUE); |
| * assertTrue(f1.compareTo(f2) > 0); |
| * assertEquals(0, f2.compareTo(f2)); |
| */ |
| } |
| |
| @Test |
| void testToString() { |
| Fraction f = null; |
| |
| f = Fraction.of(3, 5); |
| final String str = f.toString(); |
| assertEquals("3 / 5", str); |
| assertEquals(str, f.toString()); |
| |
| f = Fraction.of(7, 5); |
| assertEquals("7 / 5", f.toString()); |
| |
| f = Fraction.of(4, 2); |
| assertEquals("2", f.toString()); |
| |
| f = Fraction.of(0, 2); |
| assertEquals("0", f.toString()); |
| |
| f = Fraction.of(2, 2); |
| assertEquals("1", f.toString()); |
| |
| f = Fraction.of(Integer.MIN_VALUE); |
| assertEquals("-2147483648", f.toString()); |
| |
| f = Fraction.of(-1).add(Fraction.of(-1, Integer.MAX_VALUE)); |
| assertEquals("-2147483648 / 2147483647", f.toString()); |
| } |
| |
| /* |
| * Removed as not supported in numbers. |
| * |
| * @Test |
| * void testToProperString() { |
| * Fraction f = null; |
| * |
| * f = Fraction.of(3, 5); |
| * final String str = f.toProperString(); |
| * assertEquals("3/5", str); |
| * assertSame(str, f.toProperString()); |
| * |
| * f = Fraction.of(7, 5); |
| * assertEquals("1 2/5", f.toProperString()); |
| * |
| * f = Fraction.of(14, 10); |
| * assertEquals("1 2/5", f.toProperString()); |
| * |
| * f = Fraction.of(4, 2); |
| * assertEquals("2", f.toProperString()); |
| * |
| * f = Fraction.of(0, 2); |
| * assertEquals("0", f.toProperString()); |
| * |
| * f = Fraction.of(2, 2); |
| * assertEquals("1", f.toProperString()); |
| * |
| * f = Fraction.of(-7, 5); |
| * assertEquals("-1 2/5", f.toProperString()); |
| * |
| * f = Fraction.of(Integer.MIN_VALUE, 0, 1); |
| * assertEquals("-2147483648", f.toProperString()); |
| * |
| * f = Fraction.of(-1, 1, Integer.MAX_VALUE); |
| * assertEquals("-1 1/2147483647", f.toProperString()); |
| * |
| * assertEquals("-1", Fraction.of(-1).toProperString()); |
| * } |
| */ |
| |
| /** |
| * Assert the specified operation on the fraction throws the expected type. |
| * This method exists to ensure the fractions are constructed without an exception |
| * and the operation is tested to throw the exception. |
| * |
| * @param <T> the generic type |
| * @param expectedType the expected type |
| * @param f the fraction |
| * @param operation the operation |
| * @return the throwable |
| */ |
| private static <T extends Throwable> T assertOperationThrows(Class<T> expectedType, |
| Fraction f, UnaryOperator<Fraction> operation) { |
| return assertThrows(expectedType, () -> operation.apply(f)); |
| } |
| |
| /** |
| * Assert the specified operation on two fractions throws the expected type. |
| * This method exists to ensure the fractions are constructed without an exception |
| * and the operation is tested to throw the exception. |
| * |
| * @param <T> the generic type |
| * @param expectedType the expected type |
| * @param f1 the first fraction |
| * @param f2 the second fraction |
| * @param operation the operation |
| * @return the throwable |
| */ |
| private static <T extends Throwable> T assertOperationThrows(Class<T> expectedType, |
| Fraction f1, Fraction f2, BiFunction<Fraction, Fraction, Fraction> operation) { |
| return assertThrows(expectedType, () -> operation.apply(f1, f2)); |
| } |
| } |