View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.numbers.fraction;
18  
19  import java.util.ArrayList;
20  import java.util.Arrays;
21  import java.util.List;
22  import org.apache.commons.numbers.core.TestUtils;
23  import org.apache.commons.numbers.fraction.CommonTestCases.BinaryIntOperatorTestCase;
24  import org.apache.commons.numbers.fraction.CommonTestCases.BinaryOperatorTestCase;
25  import org.junit.jupiter.api.Assertions;
26  import org.junit.jupiter.api.Test;
27  
28  /**
29   * Tests for {@link Fraction}.
30   */
31  class FractionTest {
32  
33      /** The zero representation with positive denominator. */
34      private static final Fraction ZERO_P = Fraction.of(0, 1);
35      /** The zero representation with negative denominator. */
36      private static final Fraction ZERO_N = Fraction.of(0, -1);
37  
38      private static void assertFraction(int expectedNumerator, int expectedDenominator, Fraction actual) {
39          Assertions.assertEquals(expectedNumerator, actual.getNumerator());
40          Assertions.assertEquals(expectedDenominator, actual.getDenominator());
41          Assertions.assertEquals(
42              Integer.signum(expectedNumerator) * Integer.signum(expectedDenominator),
43              actual.signum());
44      }
45  
46      private static void assertDoubleValue(double expected, int numerator, int denominator) {
47          final Fraction f = Fraction.of(numerator, denominator);
48          Assertions.assertEquals(expected, f.doubleValue());
49      }
50  
51      @Test
52      void testConstructor() {
53          for (final CommonTestCases.UnaryOperatorTestCase testCase : CommonTestCases.numDenConstructorTestCases()) {
54              assertFraction(
55                      testCase.expectedNumerator,
56                      testCase.expectedDenominator,
57                      Fraction.of(testCase.operandNumerator, testCase.operandDenominator)
58              );
59          }
60  
61          // Special cases.
62          assertFraction(Integer.MIN_VALUE, -1, Fraction.of(Integer.MIN_VALUE, -1));
63          assertFraction(1, Integer.MIN_VALUE, Fraction.of(1, Integer.MIN_VALUE));
64          assertFraction(-1, Integer.MIN_VALUE, Fraction.of(-1, Integer.MIN_VALUE));
65          assertFraction(1, 1, Fraction.of(Integer.MIN_VALUE, Integer.MIN_VALUE));
66  
67          // Divide by zero
68          Assertions.assertThrows(ArithmeticException.class, () -> Fraction.of(1, 0));
69      }
70  
71      @Test
72      void testConstructorZero() {
73          Assertions.assertSame(Fraction.ZERO, Fraction.from(0.0));
74          Assertions.assertSame(Fraction.ZERO, Fraction.from(0.0, 1e-10, 100));
75          Assertions.assertSame(Fraction.ZERO, Fraction.from(0.0, 100));
76          Assertions.assertSame(Fraction.ZERO, Fraction.of(0));
77          Assertions.assertSame(Fraction.ZERO, Fraction.of(0, 1));
78          Assertions.assertSame(Fraction.ZERO, Fraction.of(0, -1));
79      }
80  
81      // MATH-179
82      @Test
83      void testDoubleConstructor() {
84          for (final CommonTestCases.DoubleToFractionTestCase testCase : CommonTestCases.doubleConstructorTestCases()) {
85              assertFraction(
86                      testCase.expectedNumerator,
87                      testCase.expectedDenominator,
88                      Fraction.from(testCase.operand)
89              );
90          }
91  
92          // Cases with different exact results from BigFraction
93          assertFraction(1, 3, Fraction.from(1.0 / 3.0));
94          assertFraction(17, 100, Fraction.from(17.0 / 100.0));
95          assertFraction(317, 100, Fraction.from(317.0 / 100.0));
96          assertFraction(-1, 3, Fraction.from(-1.0 / 3.0));
97          assertFraction(-17, 100, Fraction.from(17.0 / -100.0));
98          assertFraction(-317, 100, Fraction.from(-317.0 / 100.0));
99      }
100 
101     // MATH-181
102     // NUMBERS-147
103     @Test
104     void testDoubleConstructorWithMaxDenominator() {
105         for (final CommonTestCases.DoubleToFractionTestCase testCase : CommonTestCases.doubleMaxDenomConstructorTestCases()) {
106             assertFraction(
107                     testCase.expectedNumerator,
108                     testCase.expectedDenominator,
109                     Fraction.from(testCase.operand, testCase.maxDenominator)
110             );
111         }
112 
113         // Cases with different exact results from BigFraction
114         assertFraction(Integer.MIN_VALUE, -1, Fraction.from(Integer.MIN_VALUE * -1.0, 2));
115         assertFraction(Integer.MIN_VALUE, -3, Fraction.from(Integer.MIN_VALUE / -3.0, 10));
116         assertFraction(1, Integer.MIN_VALUE, Fraction.from(1.0 / Integer.MIN_VALUE, Integer.MIN_VALUE));
117         assertFraction(-1, Integer.MIN_VALUE, Fraction.from(-1.0 / Integer.MIN_VALUE, Integer.MIN_VALUE));
118 
119         Assertions.assertThrows(IllegalArgumentException.class, () -> Fraction.from(1.0, 0));
120     }
121 
122     @Test
123     void testDoubleConstructorThrows() {
124         final double eps = 1e-5;
125         final int maxIterations = Integer.MAX_VALUE;
126         final int maxDenominator = Integer.MAX_VALUE;
127         for (final double value : new double[] {Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY}) {
128             Assertions.assertThrows(IllegalArgumentException.class, () -> Fraction.from(value));
129             Assertions.assertThrows(IllegalArgumentException.class, () -> Fraction.from(value, eps, maxIterations));
130             Assertions.assertThrows(IllegalArgumentException.class, () -> Fraction.from(value, maxDenominator));
131         }
132         Assertions.assertThrows(IllegalArgumentException.class, () -> Fraction.from(1.0, Double.NaN, maxIterations));
133         Assertions.assertThrows(IllegalArgumentException.class, () -> Fraction.from(1.0, -1.0, maxIterations));
134         Assertions.assertThrows(IllegalArgumentException.class, () -> Fraction.from(1.0, eps, 0));
135         // Test a zero epsilon is allowed
136         assertFraction(1, 1, Fraction.from(1.0, 0, maxIterations));
137     }
138 
139     @Test
140     void testDoubleConstructorGoldenRatioThrows() {
141         // the golden ratio is notoriously a difficult number for continuous fraction
142         Assertions.assertThrows(ArithmeticException.class,
143             () -> Fraction.from((1 + Math.sqrt(5)) / 2, 1.0e-12, 25)
144         );
145     }
146 
147     // MATH-1029
148     @Test
149     void testDoubleConstructorWithMaxDenominatorOverFlow() {
150         Assertions.assertThrows(ArithmeticException.class,
151             () -> Fraction.from(1e10, 1000)
152         );
153         Assertions.assertThrows(ArithmeticException.class,
154             () -> Fraction.from(-1e10, 1000)
155         );
156     }
157 
158     @Test
159     void testDoubleConstructorOverflow() {
160         assertDoubleConstructorOverflow(0.75000000001455192);
161         assertDoubleConstructorOverflow(1.0e10);
162         assertDoubleConstructorOverflow(-1.0e10);
163         assertDoubleConstructorOverflow(-43979.60679604749);
164     }
165 
166     private void assertDoubleConstructorOverflow(final double a) {
167         Assertions.assertThrows(ArithmeticException.class,
168             () -> Fraction.from(a, 1.0e-12, 1000)
169         );
170     }
171 
172     @Test
173     void testDoubleConstructorWithEpsilonLimit() {
174         assertFraction(2, 5, Fraction.from(0.4, 1.0e-5, 100));
175 
176         assertFraction(3, 5,      Fraction.from(0.6152, 0.02, 100));
177         assertFraction(8, 13,     Fraction.from(0.6152, 1.0e-3, 100));
178         assertFraction(251, 408,  Fraction.from(0.6152, 1.0e-4, 100));
179         assertFraction(251, 408,  Fraction.from(0.6152, 1.0e-5, 100));
180         assertFraction(510, 829,  Fraction.from(0.6152, 1.0e-6, 100));
181         assertFraction(769, 1250, Fraction.from(0.6152, 1.0e-7, 100));
182     }
183 
184     @Test
185     void testCompareTo() {
186         final Fraction a = Fraction.of(1, 2);
187         final Fraction b = Fraction.of(1, 3);
188         final Fraction c = Fraction.of(1, 2);
189         final Fraction d = Fraction.of(-1, 2);
190         final Fraction e = Fraction.of(1, -2);
191         final Fraction f = Fraction.of(-1, -2);
192         final Fraction g = Fraction.of(-1, Integer.MIN_VALUE);
193 
194         Assertions.assertEquals(0, a.compareTo(a));
195         Assertions.assertEquals(0, a.compareTo(c));
196         Assertions.assertEquals(1, a.compareTo(b));
197         Assertions.assertEquals(-1, b.compareTo(a));
198         Assertions.assertEquals(-1, d.compareTo(a));
199         Assertions.assertEquals(1, a.compareTo(d));
200         Assertions.assertEquals(-1, e.compareTo(a));
201         Assertions.assertEquals(1, a.compareTo(e));
202         Assertions.assertEquals(0, d.compareTo(e));
203         Assertions.assertEquals(0, a.compareTo(f));
204         Assertions.assertEquals(0, f.compareTo(a));
205         Assertions.assertEquals(1, f.compareTo(e));
206         Assertions.assertEquals(-1, e.compareTo(f));
207         Assertions.assertEquals(-1, g.compareTo(a));
208         Assertions.assertEquals(-1, g.compareTo(f));
209         Assertions.assertEquals(1, a.compareTo(g));
210         Assertions.assertEquals(-1, d.compareTo(g));
211 
212         Assertions.assertEquals(0, Fraction.of(0, 3).compareTo(Fraction.of(0, -2)));
213 
214         // these two values are different approximations of PI
215         // the first  one is approximately PI - 3.07e-18
216         // the second one is approximately PI + 1.936e-17
217         final Fraction pi1 = Fraction.of(1068966896, 340262731);
218         final Fraction pi2 = Fraction.of(411557987, 131002976);
219         Assertions.assertEquals(-1, pi1.compareTo(pi2));
220         Assertions.assertEquals(1, pi2.compareTo(pi1));
221         Assertions.assertEquals(0.0, pi1.doubleValue() - pi2.doubleValue(), 1.0e-20);
222 
223         Assertions.assertEquals(0, ZERO_P.compareTo(ZERO_N));
224     }
225 
226     @Test
227     void testDoubleValue() {
228         assertDoubleValue(0.5, 1, 2);
229         assertDoubleValue(-0.5, -1, 2);
230         assertDoubleValue(-0.5, 1, -2);
231         assertDoubleValue(0.5, -1, -2);
232         assertDoubleValue(1.0 / 3.0, 1, 3);
233 
234         Assertions.assertEquals(0.0, Fraction.ZERO.doubleValue());
235         Assertions.assertEquals(0.0, ZERO_P.doubleValue());
236         Assertions.assertEquals(0.0, ZERO_N.doubleValue());
237     }
238 
239     @Test
240     void testFloatValue() {
241         Assertions.assertEquals(0.5f, Fraction.of(1, 2).floatValue());
242         Assertions.assertEquals(0.5f, Fraction.of(-1, -2).floatValue());
243         Assertions.assertEquals(-0.5f, Fraction.of(-1, 2).floatValue());
244         Assertions.assertEquals(-0.5f, Fraction.of(1, -2).floatValue());
245 
246         final float e = 1f / 3f;
247         Assertions.assertEquals(e, Fraction.of(1, 3).floatValue());
248         Assertions.assertEquals(e, Fraction.of(-1, -3).floatValue());
249         Assertions.assertEquals(-e, Fraction.of(-1, 3).floatValue());
250         Assertions.assertEquals(-e, Fraction.of(1, -3).floatValue());
251 
252         Assertions.assertEquals(0.0f, ZERO_P.floatValue());
253         Assertions.assertEquals(0.0f, ZERO_N.floatValue());
254     }
255 
256     @Test
257     void testIntValue() {
258         Assertions.assertEquals(0, Fraction.of(1, 2).intValue());
259         Assertions.assertEquals(0, Fraction.of(-1, -2).intValue());
260         Assertions.assertEquals(0, Fraction.of(-1, 2).intValue());
261         Assertions.assertEquals(0, Fraction.of(1, -2).intValue());
262 
263         Assertions.assertEquals(1, Fraction.of(3, 2).intValue());
264         Assertions.assertEquals(1, Fraction.of(-3, -2).intValue());
265         Assertions.assertEquals(-1, Fraction.of(-3, 2).intValue());
266         Assertions.assertEquals(-1, Fraction.of(3, -2).intValue());
267 
268         Assertions.assertEquals(0, Fraction.of(1, Integer.MIN_VALUE).intValue());
269         Assertions.assertEquals(0, Fraction.of(-1, Integer.MIN_VALUE).intValue());
270         Assertions.assertEquals(Integer.MIN_VALUE, Fraction.of(Integer.MIN_VALUE, 1).intValue());
271         Assertions.assertEquals(Integer.MAX_VALUE, Fraction.of(Integer.MIN_VALUE, -1).intValue());
272 
273         Assertions.assertEquals(0, ZERO_P.intValue());
274         Assertions.assertEquals(0, ZERO_N.intValue());
275     }
276 
277     @Test
278     void testLongValue() {
279         Assertions.assertEquals(0L, Fraction.of(1, 2).longValue());
280         Assertions.assertEquals(0L, Fraction.of(-1, -2).longValue());
281         Assertions.assertEquals(0L, Fraction.of(-1, 2).longValue());
282         Assertions.assertEquals(0L, Fraction.of(1, -2).longValue());
283 
284         Assertions.assertEquals(1L, Fraction.of(3, 2).longValue());
285         Assertions.assertEquals(1L, Fraction.of(-3, -2).longValue());
286         Assertions.assertEquals(-1L, Fraction.of(-3, 2).longValue());
287         Assertions.assertEquals(-1L, Fraction.of(3, -2).longValue());
288 
289         Assertions.assertEquals(0, Fraction.of(1, Integer.MIN_VALUE).longValue());
290         Assertions.assertEquals(0, Fraction.of(-1, Integer.MIN_VALUE).longValue());
291         Assertions.assertEquals(Integer.MIN_VALUE, Fraction.of(Integer.MIN_VALUE, 1).longValue());
292         Assertions.assertEquals(Integer.MAX_VALUE + 1L, Fraction.of(Integer.MIN_VALUE, -1).longValue());
293 
294         Assertions.assertEquals(0L, ZERO_P.longValue());
295         Assertions.assertEquals(0L, ZERO_N.longValue());
296     }
297 
298     @Test
299     void testAbs() {
300         for (final CommonTestCases.UnaryOperatorTestCase testCase : CommonTestCases.absTestCases()) {
301             final Fraction f = Fraction.of(testCase.operandNumerator, testCase.operandDenominator);
302             assertFraction(testCase.expectedNumerator, testCase.expectedDenominator, f.abs());
303         }
304     }
305 
306     @Test
307     void testReciprocal() {
308         for (final CommonTestCases.UnaryOperatorTestCase testCase : CommonTestCases.reciprocalTestCases()) {
309             final Fraction f = Fraction.of(testCase.operandNumerator, testCase.operandDenominator);
310             assertFraction(testCase.expectedNumerator, testCase.expectedDenominator, f.reciprocal());
311         }
312 
313         final Fraction f = Fraction.of(0, 3);
314         Assertions.assertThrows(ArithmeticException.class, f::reciprocal);
315     }
316 
317     @Test
318     void testNegate() {
319         for (final CommonTestCases.UnaryOperatorTestCase testCase : CommonTestCases.negateTestCases()) {
320             final Fraction f = Fraction.of(testCase.operandNumerator, testCase.operandDenominator);
321             assertFraction(testCase.expectedNumerator, testCase.expectedDenominator, f.negate());
322         }
323 
324         // Test special cases of negation that differ from BigFraction.
325         final Fraction one = Fraction.of(Integer.MIN_VALUE, Integer.MIN_VALUE);
326         assertFraction(-1, 1, one.negate());
327         // Special case where the negation of the numerator is not possible.
328         final Fraction minValue = Fraction.of(Integer.MIN_VALUE, 1);
329         assertFraction(Integer.MIN_VALUE, -1, minValue.negate());
330     }
331 
332     @Test
333     void testAdd() {
334         for (final CommonTestCases.BinaryOperatorTestCase testCase : CommonTestCases.addFractionTestCases()) {
335             final Fraction f1 = Fraction.of(testCase.firstOperandNumerator, testCase.firstOperandDenominator);
336             final Fraction f2 = Fraction.of(testCase.secondOperandNumerator, testCase.secondOperandDenominator);
337             assertFraction(testCase.expectedNumerator, testCase.expectedDenominator, f1.add(f2));
338         }
339         for (final CommonTestCases.BinaryIntOperatorTestCase testCase : CommonTestCases.addIntTestCases()) {
340             final Fraction f1 = Fraction.of(testCase.firstOperandNumerator, testCase.firstOperandDenominator);
341             final int i2 = testCase.secondOperand;
342             assertFraction(testCase.expectedNumerator, testCase.expectedDenominator, f1.add(i2));
343         }
344         for (final CommonTestCases.BinaryOperatorTestCase testCase : addFractionOverflowTestCases()) {
345             final Fraction f1 = Fraction.of(testCase.firstOperandNumerator, testCase.firstOperandDenominator);
346             final Fraction f2 = Fraction.of(testCase.secondOperandNumerator, testCase.secondOperandDenominator);
347             Assertions.assertThrows(ArithmeticException.class, () -> f1.add(f2));
348         }
349         for (final CommonTestCases.BinaryIntOperatorTestCase testCase : addIntOverflowTestCases()) {
350             final Fraction f1 = Fraction.of(testCase.firstOperandNumerator, testCase.firstOperandDenominator);
351             final int i2 = testCase.secondOperand;
352             Assertions.assertThrows(ArithmeticException.class, () -> f1.add(i2));
353         }
354 
355         Assertions.assertThrows(NullPointerException.class, () -> Fraction.ONE.add((Fraction) null));
356 
357         // Edge case
358         assertFraction(Integer.MIN_VALUE, -1, Fraction.ZERO.add(Fraction.of(Integer.MIN_VALUE, -1)));
359         assertFraction(Integer.MIN_VALUE, 1, Fraction.ZERO.add(Fraction.of(Integer.MIN_VALUE, 1)));
360         assertFraction(Integer.MIN_VALUE, 1, Fraction.ZERO.add(Integer.MIN_VALUE));
361     }
362 
363     @Test
364     void testDivide() {
365         for (final CommonTestCases.BinaryOperatorTestCase testCase : CommonTestCases.divideByFractionTestCases()) {
366             final Fraction f1 = Fraction.of(testCase.firstOperandNumerator, testCase.firstOperandDenominator);
367             final Fraction f2 = Fraction.of(testCase.secondOperandNumerator, testCase.secondOperandDenominator);
368             assertFraction(testCase.expectedNumerator, testCase.expectedDenominator, f1.divide(f2));
369         }
370         for (final CommonTestCases.BinaryIntOperatorTestCase testCase : CommonTestCases.divideByIntTestCases()) {
371             final Fraction f1 = Fraction.of(testCase.firstOperandNumerator, testCase.firstOperandDenominator);
372             final int i2 = testCase.secondOperand;
373             assertFraction(testCase.expectedNumerator, testCase.expectedDenominator, f1.divide(i2));
374         }
375         for (final CommonTestCases.BinaryOperatorTestCase testCase : divideByFractionOverflowTestCases()) {
376             final Fraction f1 = Fraction.of(testCase.firstOperandNumerator, testCase.firstOperandDenominator);
377             final Fraction f2 = Fraction.of(testCase.secondOperandNumerator, testCase.secondOperandDenominator);
378             Assertions.assertThrows(ArithmeticException.class, () -> f1.divide(f2));
379         }
380         for (final CommonTestCases.BinaryIntOperatorTestCase testCase : divideByIntOverflowTestCases()) {
381             final Fraction f1 = Fraction.of(testCase.firstOperandNumerator, testCase.firstOperandDenominator);
382             final int i2 = testCase.secondOperand;
383             Assertions.assertThrows(ArithmeticException.class, () -> f1.divide(i2));
384         }
385 
386         Assertions.assertThrows(NullPointerException.class, () -> Fraction.ONE.divide((Fraction) null));
387 
388         Assertions.assertThrows(FractionException.class, () -> Fraction.of(1, 2).divide(Fraction.ZERO));
389         Assertions.assertThrows(FractionException.class, () -> Fraction.of(1, 2).divide(0));
390     }
391 
392     @Test
393     void testMultiply() {
394         for (final CommonTestCases.BinaryOperatorTestCase testCase : CommonTestCases.multiplyByFractionTestCases()) {
395             final Fraction f1 = Fraction.of(testCase.firstOperandNumerator, testCase.firstOperandDenominator);
396             final Fraction f2 = Fraction.of(testCase.secondOperandNumerator, testCase.secondOperandDenominator);
397             assertFraction(testCase.expectedNumerator, testCase.expectedDenominator, f1.multiply(f2));
398         }
399         for (final CommonTestCases.BinaryIntOperatorTestCase testCase : CommonTestCases.multiplyByIntTestCases()) {
400             final Fraction f1 = Fraction.of(testCase.firstOperandNumerator, testCase.firstOperandDenominator);
401             final int i2 = testCase.secondOperand;
402             assertFraction(testCase.expectedNumerator, testCase.expectedDenominator, f1.multiply(i2));
403         }
404         for (final CommonTestCases.BinaryOperatorTestCase testCase : multiplyByFractionOverflowTestCases()) {
405             final Fraction f1 = Fraction.of(testCase.firstOperandNumerator, testCase.firstOperandDenominator);
406             final Fraction f2 = Fraction.of(testCase.secondOperandNumerator, testCase.secondOperandDenominator);
407             Assertions.assertThrows(ArithmeticException.class, () -> f1.multiply(f2));
408         }
409         for (final CommonTestCases.BinaryIntOperatorTestCase testCase : multiplyByIntOverflowTestCases()) {
410             final Fraction f1 = Fraction.of(testCase.firstOperandNumerator, testCase.firstOperandDenominator);
411             final int i2 = testCase.secondOperand;
412             Assertions.assertThrows(ArithmeticException.class, () -> f1.multiply(i2));
413         }
414 
415         Assertions.assertThrows(NullPointerException.class, () -> Fraction.ONE.multiply((Fraction) null));
416     }
417 
418     @Test
419     void testPow() {
420         for (final CommonTestCases.BinaryIntOperatorTestCase testCase : CommonTestCases.powTestCases()) {
421             final Fraction f1 = Fraction.of(testCase.firstOperandNumerator, testCase.firstOperandDenominator);
422             final int exponent = testCase.secondOperand;
423             assertFraction(testCase.expectedNumerator, testCase.expectedDenominator, f1.pow(exponent));
424         }
425 
426         Assertions.assertThrows(ArithmeticException.class, () -> Fraction.of(Integer.MAX_VALUE).pow(2));
427         Assertions.assertThrows(ArithmeticException.class, () -> Fraction.of(1, Integer.MAX_VALUE).pow(2));
428         Assertions.assertThrows(ArithmeticException.class, () -> Fraction.of(Integer.MAX_VALUE).pow(-2));
429         Assertions.assertThrows(ArithmeticException.class, () -> Fraction.of(1, Integer.MAX_VALUE).pow(-2));
430     }
431 
432     @Test
433     void testSubtract() {
434         for (final CommonTestCases.BinaryOperatorTestCase testCase : CommonTestCases.subtractFractionTestCases()) {
435             final Fraction f1 = Fraction.of(testCase.firstOperandNumerator, testCase.firstOperandDenominator);
436             final Fraction f2 = Fraction.of(testCase.secondOperandNumerator, testCase.secondOperandDenominator);
437             assertFraction(testCase.expectedNumerator, testCase.expectedDenominator, f1.subtract(f2));
438         }
439         for (final CommonTestCases.BinaryIntOperatorTestCase testCase : CommonTestCases.subtractIntTestCases()) {
440             final Fraction f1 = Fraction.of(testCase.firstOperandNumerator, testCase.firstOperandDenominator);
441             final int i2 = testCase.secondOperand;
442             assertFraction(testCase.expectedNumerator, testCase.expectedDenominator, f1.subtract(i2));
443         }
444         for (final CommonTestCases.BinaryOperatorTestCase testCase : subtractFractionOverflowTestCases()) {
445             final Fraction f1 = Fraction.of(testCase.firstOperandNumerator, testCase.firstOperandDenominator);
446             final Fraction f2 = Fraction.of(testCase.secondOperandNumerator, testCase.secondOperandDenominator);
447             Assertions.assertThrows(ArithmeticException.class, () -> f1.subtract(f2));
448         }
449         for (final CommonTestCases.BinaryIntOperatorTestCase testCase : subtractIntOverflowTestCases()) {
450             final Fraction f1 = Fraction.of(testCase.firstOperandNumerator, testCase.firstOperandDenominator);
451             final int i2 = testCase.secondOperand;
452             Assertions.assertThrows(ArithmeticException.class, () -> f1.subtract(i2));
453         }
454 
455         Assertions.assertThrows(NullPointerException.class, () -> Fraction.ONE.add((Fraction) null));
456 
457         // Edge case
458         assertFraction(Integer.MIN_VALUE, 1, Fraction.ZERO.subtract(Fraction.of(Integer.MIN_VALUE, -1)));
459         assertFraction(Integer.MIN_VALUE, -1, Fraction.ZERO.subtract(Fraction.of(Integer.MIN_VALUE, 1)));
460         assertFraction(Integer.MIN_VALUE, -1, Fraction.ZERO.subtract(Integer.MIN_VALUE));
461     }
462 
463     @Test
464     void testEqualsAndHashCode() {
465         final Fraction zero = Fraction.of(0, 1);
466         Assertions.assertEquals(zero, zero);
467         Assertions.assertNotEquals(zero, null);
468         Assertions.assertNotEquals(zero, new Object());
469         Assertions.assertNotEquals(zero, Double.valueOf(0));
470 
471         // Equal to same rational number
472         final Fraction zero2 = Fraction.of(0, 2);
473         assertEqualAndHashCodeEqual(zero, zero2);
474 
475         // Not equal to different rational number
476         final Fraction one = Fraction.of(1, 1);
477         Assertions.assertNotEquals(zero, one);
478         Assertions.assertNotEquals(one, zero);
479 
480         // Test using different representations of the same fraction
481         // (Denominators are primes)
482         for (final int[] f : new int[][] {{1, 1}, {2, 3}, {6826, 15373}, {1373, 103813}, {0, 3}}) {
483             final int num = f[0];
484             final int den = f[1];
485             Fraction f1 = Fraction.of(-num, den);
486             Fraction f2 = Fraction.of(num, -den);
487             assertEqualAndHashCodeEqual(f1, f2);
488             assertEqualAndHashCodeEqual(f2, f1);
489             f1 = Fraction.of(num, den);
490             f2 = Fraction.of(-num, -den);
491             assertEqualAndHashCodeEqual(f1, f2);
492             assertEqualAndHashCodeEqual(f2, f1);
493         }
494 
495         // Same numerator or denominator as 1/1
496         final Fraction half = Fraction.of(1, 2);
497         final Fraction two = Fraction.of(2, 1);
498         Assertions.assertNotEquals(one, half);
499         Assertions.assertNotEquals(one, two);
500 
501         // Check worst case fractions which will have a component using MIN_VALUE.
502         // Note: abs(MIN_VALUE) is negative but this should not effect the equals result.
503         final Fraction almostOne = Fraction.of(Integer.MIN_VALUE, Integer.MAX_VALUE);
504         final Fraction almostOne2 = Fraction.of(Integer.MIN_VALUE, -Integer.MAX_VALUE);
505         Assertions.assertEquals(almostOne, almostOne);
506         Assertions.assertNotEquals(almostOne, almostOne2);
507         final Fraction almostZero = Fraction.of(-1, Integer.MIN_VALUE);
508         final Fraction almostZero2 = Fraction.of(1, Integer.MIN_VALUE);
509         Assertions.assertEquals(almostZero, almostZero);
510         Assertions.assertNotEquals(almostZero, almostZero2);
511     }
512 
513     /**
514      * Assert the two fractions are equal. The contract of {@link Object#hashCode()} requires
515      * that the hash code must also be equal.
516      *
517      * <p>Ideally this method should not be called with the same instance for both arguments.
518      * It is intended to be used to test different objects that are equal have the same hash code.
519      * However the same object may be constructed for different arguments using factory
520      * constructors, e.g. zero.
521      *
522      * @param f1 Fraction 1.
523      * @param f2 Fraction 2.
524      */
525     private static void assertEqualAndHashCodeEqual(Fraction f1, Fraction f2) {
526         Assertions.assertEquals(f1, f2);
527         Assertions.assertEquals(f1.hashCode(), f2.hashCode(), "Equal fractions have different hashCode");
528         // Check the computation matches the result of Arrays.hashCode and the signum.
529         // This is not mandated but is a recommendation.
530         final int expected = f1.signum() *
531                              Arrays.hashCode(new int[] {Math.abs(f1.getNumerator()),
532                                                         Math.abs(f1.getDenominator())});
533         Assertions.assertEquals(expected, f1.hashCode(), "Hashcode not equal to using Arrays.hashCode");
534     }
535 
536     @Test
537     void testAdditiveNeutral() {
538         Assertions.assertEquals(Fraction.ZERO, Fraction.ONE.zero());
539     }
540 
541     @Test
542     void testMultiplicativeNeutral() {
543         Assertions.assertEquals(Fraction.ONE, Fraction.ZERO.one());
544     }
545 
546     @Test
547     void testSerial() {
548         final Fraction[] fractions = {
549             Fraction.of(3, 4), Fraction.ONE, Fraction.ZERO,
550             Fraction.of(17), Fraction.from(Math.PI, 1000),
551             Fraction.of(-5, 2)
552         };
553         for (final Fraction fraction : fractions) {
554             Assertions.assertEquals(fraction,
555                                     TestUtils.serializeAndRecover(fraction));
556         }
557     }
558 
559     @Test
560     void testToString() {
561         Assertions.assertEquals("0", Fraction.of(0, 3).toString());
562         Assertions.assertEquals("0", Fraction.of(0, -3).toString());
563         Assertions.assertEquals("3", Fraction.of(6, 2).toString());
564         Assertions.assertEquals("2 / 3", Fraction.of(18, 27).toString());
565         Assertions.assertEquals("-10 / 11", Fraction.of(-10, 11).toString());
566         Assertions.assertEquals("10 / -11", Fraction.of(10, -11).toString());
567     }
568 
569     @Test
570     void testParse() {
571         final String[] validExpressions = new String[] {
572             "1 / 2",
573             "-1 / 2",
574             "1 / -2",
575             "-1 / -2",
576             "01 / 2",
577             "01 / 02",
578             "-01 / 02",
579             "01 / -02",
580             "15 / 16",
581             "-2 / 3",
582             "8 / 7",
583             "5",
584             "-3",
585             "-3"
586         };
587         final Fraction[] fractions = {
588             Fraction.of(1, 2),
589             Fraction.of(-1, 2),
590             Fraction.of(1, -2),
591             Fraction.of(-1, -2),
592             Fraction.of(1, 2),
593             Fraction.of(1, 2),
594             Fraction.of(-1, 2),
595             Fraction.of(1, -2),
596             Fraction.of(15, 16),
597             Fraction.of(-2, 3),
598             Fraction.of(8, 7),
599             Fraction.of(5, 1),
600             Fraction.of(-3, 1),
601             Fraction.of(3, -1),
602         };
603         int inc = 0;
604         for (final Fraction fraction : fractions) {
605             Assertions.assertEquals(fraction,
606                                     Fraction.parse(validExpressions[inc]));
607             inc++;
608         }
609 
610         Assertions.assertThrows(NumberFormatException.class, () -> Fraction.parse("1 // 2"));
611         Assertions.assertThrows(NumberFormatException.class, () -> Fraction.parse("1 / z"));
612         Assertions.assertThrows(NumberFormatException.class, () -> Fraction.parse("1 / --2"));
613         Assertions.assertThrows(NumberFormatException.class, () -> Fraction.parse("x"));
614     }
615 
616     @Test
617     void testMath1261() {
618         final Fraction a = Fraction.of(Integer.MAX_VALUE, 2);
619         assertFraction(Integer.MAX_VALUE, 1, a.multiply(2));
620 
621         final Fraction b = Fraction.of(2, Integer.MAX_VALUE);
622         assertFraction(1, Integer.MAX_VALUE, b.divide(2));
623     }
624 
625     @Test
626     void testNumbers150() {
627         // zero to negative powers should throw an exception
628         Assertions.assertThrows(ArithmeticException.class, () -> Fraction.ZERO.pow(-1));
629         Assertions.assertThrows(ArithmeticException.class, () -> Fraction.ZERO.pow(Integer.MIN_VALUE));
630 
631         // shall overflow
632         final Fraction f2 = Fraction.of(2);
633         Assertions.assertThrows(ArithmeticException.class, () -> f2.pow(Integer.MIN_VALUE));
634         final Fraction f12 = Fraction.of(1, 2);
635         Assertions.assertThrows(ArithmeticException.class, () -> f12.pow(Integer.MIN_VALUE));
636     }
637 
638     /**
639      * Defines test cases that cause overflow in {@link Fraction#add(Fraction)}.
640      * @return a list of test cases
641      */
642     private static List<BinaryOperatorTestCase> addFractionOverflowTestCases() {
643         final List<BinaryOperatorTestCase> testCases = new ArrayList<>();
644         testCases.add(new BinaryOperatorTestCase(1, Integer.MAX_VALUE, 1, Integer.MAX_VALUE - 1, 0, 0));
645         testCases.add(new BinaryOperatorTestCase(Integer.MIN_VALUE, 5, -1, 5, 0, 0));
646         testCases.add(new BinaryOperatorTestCase(Integer.MIN_VALUE, 1, -1, 1, 0, 0));
647         testCases.add(new BinaryOperatorTestCase(Integer.MAX_VALUE, 1, 1, 1, 0, 0));
648         testCases.add(new BinaryOperatorTestCase(3, 327680, 2, 59049, 0, 0));
649         testCases.add(new BinaryOperatorTestCase(1, 2, Integer.MIN_VALUE, -2, 0, 0));
650         return testCases;
651     }
652 
653     /**
654      * Defines test cases that cause overflow in {@link Fraction#add(int)}.
655      * @return a list of test cases
656      */
657     private static List<BinaryIntOperatorTestCase> addIntOverflowTestCases() {
658         final List<BinaryIntOperatorTestCase> testCases = new ArrayList<>();
659         testCases.add(new BinaryIntOperatorTestCase(Integer.MIN_VALUE, 1, -1, 0, 0));
660         testCases.add(new BinaryIntOperatorTestCase(Integer.MAX_VALUE, 1, 1, 0, 0));
661         testCases.add(new BinaryIntOperatorTestCase(1, 2, Integer.MIN_VALUE / -2, 0, 0));
662         return testCases;
663     }
664 
665     /**
666      * Defines test cases that cause overflow in {@link Fraction#divide(Fraction)}.
667      * @return a list of test cases
668      */
669     private static List<BinaryOperatorTestCase> divideByFractionOverflowTestCases() {
670         final List<BinaryOperatorTestCase> testCases = new ArrayList<>();
671         testCases.add(new BinaryOperatorTestCase(1, Integer.MAX_VALUE, 2, 1, 0, 0));
672         testCases.add(new BinaryOperatorTestCase(1, Integer.MAX_VALUE, -2, 1, 0, 0));
673         testCases.add(new BinaryOperatorTestCase(1, Integer.MIN_VALUE, 2, 1, 0, 0));
674         testCases.add(new BinaryOperatorTestCase(1, Integer.MIN_VALUE, -2, 1, 0, 0));
675         return testCases;
676     }
677 
678     /**
679      * Defines test cases that cause overflow in {@link Fraction#divide(int)}.
680      * @return a list of test cases
681      */
682     private static List<BinaryIntOperatorTestCase> divideByIntOverflowTestCases() {
683         final List<BinaryIntOperatorTestCase> testCases = new ArrayList<>();
684         testCases.add(new BinaryIntOperatorTestCase(1, Integer.MAX_VALUE, 2, 0, 0));
685         testCases.add(new BinaryIntOperatorTestCase(1, Integer.MAX_VALUE, -2, 0, 0));
686         testCases.add(new BinaryIntOperatorTestCase(1, Integer.MIN_VALUE, 2, 0, 0));
687         testCases.add(new BinaryIntOperatorTestCase(1, Integer.MIN_VALUE, -2, 0, 0));
688         return testCases;
689     }
690 
691     /**
692      * Defines test cases that cause overflow in {@link Fraction#multiply(Fraction)}.
693      * @return a list of test cases
694      */
695     private static List<BinaryOperatorTestCase> multiplyByFractionOverflowTestCases() {
696         final List<BinaryOperatorTestCase> testCases = new ArrayList<>();
697         testCases.add(new BinaryOperatorTestCase(Integer.MAX_VALUE, 1, 2, 1, 0, 0));
698         testCases.add(new BinaryOperatorTestCase(Integer.MAX_VALUE, 1, -2, 1, 0, 0));
699         testCases.add(new BinaryOperatorTestCase(Integer.MIN_VALUE, 1, 2, 1, 0, 0));
700         testCases.add(new BinaryOperatorTestCase(Integer.MIN_VALUE, 1, -2, 1, 0, 0));
701         return testCases;
702     }
703 
704     /**
705      * Defines test cases that cause overflow in {@link Fraction#multiply(int)}.
706      * @return a list of test cases
707      */
708     private static List<BinaryIntOperatorTestCase> multiplyByIntOverflowTestCases() {
709         final List<BinaryIntOperatorTestCase> testCases = new ArrayList<>();
710         testCases.add(new BinaryIntOperatorTestCase(Integer.MAX_VALUE, 1, 2, 0, 0));
711         testCases.add(new BinaryIntOperatorTestCase(Integer.MAX_VALUE, 1, -2, 0, 0));
712         testCases.add(new BinaryIntOperatorTestCase(Integer.MIN_VALUE, 1, 2, 0, 0));
713         testCases.add(new BinaryIntOperatorTestCase(Integer.MIN_VALUE, 1, -2, 0, 0));
714         return testCases;
715     }
716 
717     /**
718      * Defines test cases that cause overflow in {@link Fraction#subtract(Fraction)}.
719      * @return a list of test cases
720      */
721     private static List<BinaryOperatorTestCase> subtractFractionOverflowTestCases() {
722         final List<BinaryOperatorTestCase> testCases = new ArrayList<>();
723         testCases.add(new BinaryOperatorTestCase(1, Integer.MAX_VALUE, 1, Integer.MAX_VALUE - 1, 0, 0));
724         testCases.add(new BinaryOperatorTestCase(Integer.MIN_VALUE, 5, 1, 5, 0, 0));
725         testCases.add(new BinaryOperatorTestCase(Integer.MIN_VALUE, 1, 1, 1, 0, 0));
726         testCases.add(new BinaryOperatorTestCase(Integer.MAX_VALUE, 1, -1, 1, 0, 0));
727         testCases.add(new BinaryOperatorTestCase(3, 327680, 2, 59049, 0, 0));
728         testCases.add(new BinaryOperatorTestCase(1, 2, Integer.MIN_VALUE, 2, 0, 0));
729         return testCases;
730     }
731 
732     /**
733      * Defines test cases that cause overflow in {@link Fraction#subtract(int)}.
734      * @return a list of test cases
735      */
736     private static List<BinaryIntOperatorTestCase> subtractIntOverflowTestCases() {
737         final List<BinaryIntOperatorTestCase> testCases = new ArrayList<>();
738         testCases.add(new BinaryIntOperatorTestCase(Integer.MIN_VALUE, 1, 1, 0, 0));
739         testCases.add(new BinaryIntOperatorTestCase(Integer.MAX_VALUE, 1, -1, 0, 0));
740         testCases.add(new BinaryIntOperatorTestCase(1, 2, Integer.MIN_VALUE / 2, 0, 0));
741         return testCases;
742     }
743 }