View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   * https://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.commons.lang3.math;
20  
21  import static org.apache.commons.lang3.LangAssertions.assertNullPointerException;
22  import static org.junit.jupiter.api.Assertions.assertEquals;
23  import static org.junit.jupiter.api.Assertions.assertNotEquals;
24  import static org.junit.jupiter.api.Assertions.assertSame;
25  import static org.junit.jupiter.api.Assertions.assertThrows;
26  import static org.junit.jupiter.api.Assertions.assertTrue;
27  
28  import org.apache.commons.lang3.AbstractLangTest;
29  import org.junit.jupiter.api.Test;
30  import org.junit.jupiter.params.ParameterizedTest;
31  import org.junit.jupiter.params.provider.CsvSource;
32  
33  /**
34   * Test cases for the {@link Fraction} class
35   */
36  class FractionTest extends AbstractLangTest {
37  
38      private static final int SKIP = 500; // 53
39  
40      @Test
41      void testAbs() {
42          Fraction f;
43  
44          f = Fraction.getFraction(50, 75);
45          f = f.abs();
46          assertEquals(50, f.getNumerator());
47          assertEquals(75, f.getDenominator());
48  
49          f = Fraction.getFraction(-50, 75);
50          f = f.abs();
51          assertEquals(50, f.getNumerator());
52          assertEquals(75, f.getDenominator());
53  
54          f = Fraction.getFraction(Integer.MAX_VALUE, 1);
55          f = f.abs();
56          assertEquals(Integer.MAX_VALUE, f.getNumerator());
57          assertEquals(1, f.getDenominator());
58  
59          f = Fraction.getFraction(Integer.MAX_VALUE, -1);
60          f = f.abs();
61          assertEquals(Integer.MAX_VALUE, f.getNumerator());
62          assertEquals(1, f.getDenominator());
63  
64          assertThrows(ArithmeticException.class, () -> Fraction.getFraction(Integer.MIN_VALUE, 1).abs());
65      }
66  
67      @Test
68      void testAdd() {
69          Fraction f;
70          Fraction f1;
71          Fraction f2;
72  
73          f1 = Fraction.getFraction(3, 5);
74          f2 = Fraction.getFraction(1, 5);
75          f = f1.add(f2);
76          assertEquals(4, f.getNumerator());
77          assertEquals(5, f.getDenominator());
78  
79          f1 = Fraction.getFraction(3, 5);
80          f2 = Fraction.getFraction(2, 5);
81          f = f1.add(f2);
82          assertEquals(1, f.getNumerator());
83          assertEquals(1, f.getDenominator());
84  
85          f1 = Fraction.getFraction(3, 5);
86          f2 = Fraction.getFraction(3, 5);
87          f = f1.add(f2);
88          assertEquals(6, f.getNumerator());
89          assertEquals(5, f.getDenominator());
90  
91          f1 = Fraction.getFraction(3, 5);
92          f2 = Fraction.getFraction(-4, 5);
93          f = f1.add(f2);
94          assertEquals(-1, f.getNumerator());
95          assertEquals(5, f.getDenominator());
96  
97          f1 = Fraction.getFraction(Integer.MAX_VALUE - 1, 1);
98          f2 = Fraction.ONE;
99          f = f1.add(f2);
100         assertEquals(Integer.MAX_VALUE, f.getNumerator());
101         assertEquals(1, f.getDenominator());
102 
103         f1 = Fraction.getFraction(3, 5);
104         f2 = Fraction.getFraction(1, 2);
105         f = f1.add(f2);
106         assertEquals(11, f.getNumerator());
107         assertEquals(10, f.getDenominator());
108 
109         f1 = Fraction.getFraction(3, 8);
110         f2 = Fraction.getFraction(1, 6);
111         f = f1.add(f2);
112         assertEquals(13, f.getNumerator());
113         assertEquals(24, f.getDenominator());
114 
115         f1 = Fraction.getFraction(0, 5);
116         f2 = Fraction.getFraction(1, 5);
117         f = f1.add(f2);
118         assertSame(f2, f);
119         f = f2.add(f1);
120         assertSame(f2, f);
121 
122         f1 = Fraction.getFraction(-1, 13 * 13 * 2 * 2);
123         f2 = Fraction.getFraction(-2, 13 * 17 * 2);
124         final Fraction fr = f1.add(f2);
125         assertEquals(13 * 13 * 17 * 2 * 2, fr.getDenominator());
126         assertEquals(-17 - 2 * 13 * 2, fr.getNumerator());
127 
128         assertNullPointerException(() -> fr.add(null));
129 
130         // if this fraction is added naively, it will overflow.
131         // check that it doesn't.
132         f1 = Fraction.getFraction(1, 32768 * 3);
133         f2 = Fraction.getFraction(1, 59049);
134         f = f1.add(f2);
135         assertEquals(52451, f.getNumerator());
136         assertEquals(1934917632, f.getDenominator());
137 
138         f1 = Fraction.getFraction(Integer.MIN_VALUE, 3);
139         f2 = Fraction.ONE_THIRD;
140         f = f1.add(f2);
141         assertEquals(Integer.MIN_VALUE + 1, f.getNumerator());
142         assertEquals(3, f.getDenominator());
143 
144         f1 = Fraction.getFraction(Integer.MAX_VALUE - 1, 1);
145         f2 = Fraction.ONE;
146         f = f1.add(f2);
147         assertEquals(Integer.MAX_VALUE, f.getNumerator());
148         assertEquals(1, f.getDenominator());
149 
150         final Fraction overflower = f;
151         assertThrows(ArithmeticException.class, () -> overflower.add(Fraction.ONE)); // should overflow
152 
153         // denominator should not be a multiple of 2 or 3 to trigger overflow
154         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(Integer.MIN_VALUE, 5).add(Fraction.getFraction(-1, 5)));
155 
156         final Fraction maxValue = Fraction.getFraction(-Integer.MAX_VALUE, 1);
157         assertThrows(ArithmeticException.class, () -> maxValue.add(maxValue));
158 
159         final Fraction negativeMaxValue = Fraction.getFraction(-Integer.MAX_VALUE, 1);
160         assertThrows(ArithmeticException.class, () -> negativeMaxValue.add(negativeMaxValue));
161 
162         final Fraction f3 = Fraction.getFraction(3, 327680);
163         final Fraction f4 = Fraction.getFraction(2, 59049);
164         assertThrows(ArithmeticException.class, () -> f3.add(f4)); // should overflow
165     }
166 
167     @Test
168     void testCompareTo() {
169         final Fraction f1;
170         Fraction f2;
171 
172         f1 = Fraction.getFraction(3, 5);
173         assertEquals(0, f1.compareTo(f1));
174 
175         final Fraction fr = f1;
176         assertNullPointerException(() -> fr.compareTo(null));
177 
178         f2 = Fraction.getFraction(2, 5);
179         assertTrue(f1.compareTo(f2) > 0);
180         assertEquals(0, f2.compareTo(f2));
181 
182         f2 = Fraction.getFraction(4, 5);
183         assertTrue(f1.compareTo(f2) < 0);
184         assertEquals(0, f2.compareTo(f2));
185 
186         f2 = Fraction.getFraction(3, 5);
187         assertEquals(0, f1.compareTo(f2));
188         assertEquals(0, f2.compareTo(f2));
189 
190         f2 = Fraction.getFraction(6, 10);
191         assertEquals(0, f1.compareTo(f2));
192         assertEquals(0, f2.compareTo(f2));
193 
194         f2 = Fraction.getFraction(-1, 1, Integer.MAX_VALUE);
195         assertTrue(f1.compareTo(f2) > 0);
196         assertEquals(0, f2.compareTo(f2));
197 
198     }
199 
200     @Test
201     void testConstants() {
202         assertEquals(0, Fraction.ZERO.getNumerator());
203         assertEquals(1, Fraction.ZERO.getDenominator());
204 
205         assertEquals(1, Fraction.ONE.getNumerator());
206         assertEquals(1, Fraction.ONE.getDenominator());
207 
208         assertEquals(1, Fraction.ONE_HALF.getNumerator());
209         assertEquals(2, Fraction.ONE_HALF.getDenominator());
210 
211         assertEquals(1, Fraction.ONE_THIRD.getNumerator());
212         assertEquals(3, Fraction.ONE_THIRD.getDenominator());
213 
214         assertEquals(2, Fraction.TWO_THIRDS.getNumerator());
215         assertEquals(3, Fraction.TWO_THIRDS.getDenominator());
216 
217         assertEquals(1, Fraction.ONE_QUARTER.getNumerator());
218         assertEquals(4, Fraction.ONE_QUARTER.getDenominator());
219 
220         assertEquals(2, Fraction.TWO_QUARTERS.getNumerator());
221         assertEquals(4, Fraction.TWO_QUARTERS.getDenominator());
222 
223         assertEquals(3, Fraction.THREE_QUARTERS.getNumerator());
224         assertEquals(4, Fraction.THREE_QUARTERS.getDenominator());
225 
226         assertEquals(1, Fraction.ONE_FIFTH.getNumerator());
227         assertEquals(5, Fraction.ONE_FIFTH.getDenominator());
228 
229         assertEquals(2, Fraction.TWO_FIFTHS.getNumerator());
230         assertEquals(5, Fraction.TWO_FIFTHS.getDenominator());
231 
232         assertEquals(3, Fraction.THREE_FIFTHS.getNumerator());
233         assertEquals(5, Fraction.THREE_FIFTHS.getDenominator());
234 
235         assertEquals(4, Fraction.FOUR_FIFTHS.getNumerator());
236         assertEquals(5, Fraction.FOUR_FIFTHS.getDenominator());
237     }
238 
239     @Test
240     void testConversions() {
241         final Fraction f;
242 
243         f = Fraction.getFraction(3, 7, 8);
244         assertEquals(3, f.intValue());
245         assertEquals(3L, f.longValue());
246         assertEquals(3.875f, f.floatValue(), 0.00001f);
247         assertEquals(3.875d, f.doubleValue(), 0.00001d);
248     }
249 
250     @Test
251     void testDivide() {
252         Fraction f;
253         Fraction f1;
254         Fraction f2;
255 
256         f1 = Fraction.getFraction(3, 5);
257         f2 = Fraction.getFraction(2, 5);
258         f = f1.divideBy(f2);
259         assertEquals(3, f.getNumerator());
260         assertEquals(2, f.getDenominator());
261 
262         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(3, 5).divideBy(Fraction.ZERO));
263 
264         f1 = Fraction.getFraction(0, 5);
265         f2 = Fraction.getFraction(2, 7);
266         f = f1.divideBy(f2);
267         assertSame(Fraction.ZERO, f);
268 
269         f1 = Fraction.getFraction(2, 7);
270         f2 = Fraction.ONE;
271         f = f1.divideBy(f2);
272         assertEquals(2, f.getNumerator());
273         assertEquals(7, f.getDenominator());
274 
275         f1 = Fraction.getFraction(1, Integer.MAX_VALUE);
276         f = f1.divideBy(f1);
277         assertEquals(1, f.getNumerator());
278         assertEquals(1, f.getDenominator());
279 
280         f1 = Fraction.getFraction(Integer.MIN_VALUE, Integer.MAX_VALUE);
281         f2 = Fraction.getFraction(1, Integer.MAX_VALUE);
282         final Fraction fr = f1.divideBy(f2);
283         assertEquals(Integer.MIN_VALUE, fr.getNumerator());
284         assertEquals(1, fr.getDenominator());
285 
286         assertNullPointerException(() -> fr.divideBy(null));
287 
288         final Fraction smallest = Fraction.getFraction(1, Integer.MAX_VALUE);
289         assertThrows(ArithmeticException.class, () -> smallest.divideBy(smallest.invert())); // Should overflow
290 
291         final Fraction negative = Fraction.getFraction(1, -Integer.MAX_VALUE);
292         assertThrows(ArithmeticException.class, () -> negative.divideBy(negative.invert())); // Should overflow
293     }
294 
295     @Test
296     void testEquals() {
297         Fraction f1;
298         Fraction f2;
299 
300         f1 = Fraction.getFraction(3, 5);
301         assertNotEquals(null, f1);
302         assertNotEquals(f1, new Object());
303         assertNotEquals(f1, Integer.valueOf(6));
304 
305         f1 = Fraction.getFraction(3, 5);
306         f2 = Fraction.getFraction(2, 5);
307         assertNotEquals(f1, f2);
308         assertEquals(f1, f1);
309         assertEquals(f2, f2);
310 
311         f2 = Fraction.getFraction(3, 5);
312         assertEquals(f1, f2);
313 
314         f2 = Fraction.getFraction(6, 10);
315         assertNotEquals(f1, f2);
316     }
317 
318     @Test
319     void testFactory_double() {
320         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(Double.NaN));
321         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(Double.POSITIVE_INFINITY));
322         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(Double.NEGATIVE_INFINITY));
323         assertThrows(ArithmeticException.class, () -> Fraction.getFraction((double) Integer.MAX_VALUE + 1));
324 
325         // zero
326         Fraction f = Fraction.getFraction(0.0d);
327         assertEquals(0, f.getNumerator());
328         assertEquals(1, f.getDenominator());
329 
330         // one
331         f = Fraction.getFraction(1.0d);
332         assertEquals(1, f.getNumerator());
333         assertEquals(1, f.getDenominator());
334 
335         // one half
336         f = Fraction.getFraction(0.5d);
337         assertEquals(1, f.getNumerator());
338         assertEquals(2, f.getDenominator());
339 
340         // negative
341         f = Fraction.getFraction(-0.875d);
342         assertEquals(-7, f.getNumerator());
343         assertEquals(8, f.getDenominator());
344 
345         // over 1
346         f = Fraction.getFraction(1.25d);
347         assertEquals(5, f.getNumerator());
348         assertEquals(4, f.getDenominator());
349 
350         // two thirds
351         f = Fraction.getFraction(0.66666d);
352         assertEquals(2, f.getNumerator());
353         assertEquals(3, f.getDenominator());
354 
355         // small
356         f = Fraction.getFraction(1.0d / 10001d);
357         assertEquals(0, f.getNumerator());
358         assertEquals(1, f.getDenominator());
359 
360         // normal
361         Fraction f2;
362         for (int i = 1; i <= 100; i++) { // denominator
363             for (int j = 1; j <= i; j++) { // numerator
364                 f = Fraction.getFraction((double) j / (double) i);
365 
366                 f2 = Fraction.getReducedFraction(j, i);
367                 assertEquals(f2.getNumerator(), f.getNumerator());
368                 assertEquals(f2.getDenominator(), f.getDenominator());
369             }
370         }
371         // save time by skipping some tests! (
372         for (int i = 1001; i <= 10000; i += SKIP) { // denominator
373             for (int j = 1; j <= i; j++) { // numerator
374                 f = Fraction.getFraction((double) j / (double) i);
375                 f2 = Fraction.getReducedFraction(j, i);
376                 assertEquals(f2.getNumerator(), f.getNumerator());
377                 assertEquals(f2.getDenominator(), f.getDenominator());
378             }
379         }
380     }
381 
382     @Test
383     void testFactory_int_int() {
384         Fraction f;
385 
386         // zero
387         f = Fraction.getFraction(0, 1);
388         assertEquals(0, f.getNumerator());
389         assertEquals(1, f.getDenominator());
390 
391         f = Fraction.getFraction(0, 2);
392         assertEquals(0, f.getNumerator());
393         assertEquals(2, f.getDenominator());
394 
395         // normal
396         f = Fraction.getFraction(1, 1);
397         assertEquals(1, f.getNumerator());
398         assertEquals(1, f.getDenominator());
399 
400         f = Fraction.getFraction(2, 1);
401         assertEquals(2, f.getNumerator());
402         assertEquals(1, f.getDenominator());
403 
404         f = Fraction.getFraction(23, 345);
405         assertEquals(23, f.getNumerator());
406         assertEquals(345, f.getDenominator());
407 
408         // improper
409         f = Fraction.getFraction(22, 7);
410         assertEquals(22, f.getNumerator());
411         assertEquals(7, f.getDenominator());
412 
413         // negatives
414         f = Fraction.getFraction(-6, 10);
415         assertEquals(-6, f.getNumerator());
416         assertEquals(10, f.getDenominator());
417 
418         f = Fraction.getFraction(6, -10);
419         assertEquals(-6, f.getNumerator());
420         assertEquals(10, f.getDenominator());
421 
422         f = Fraction.getFraction(-6, -10);
423         assertEquals(6, f.getNumerator());
424         assertEquals(10, f.getDenominator());
425 
426         // zero denominator
427         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(1, 0));
428         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(2, 0));
429         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(-3, 0));
430 
431         // very large: can't represent as unsimplified fraction, although
432         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(4, Integer.MIN_VALUE));
433         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(1, Integer.MIN_VALUE));
434     }
435 
436     @Test
437     void testFactory_int_int_int() {
438         Fraction f;
439 
440         // zero
441         f = Fraction.getFraction(0, 0, 2);
442         assertEquals(0, f.getNumerator());
443         assertEquals(2, f.getDenominator());
444 
445         f = Fraction.getFraction(2, 0, 2);
446         assertEquals(4, f.getNumerator());
447         assertEquals(2, f.getDenominator());
448 
449         f = Fraction.getFraction(0, 1, 2);
450         assertEquals(1, f.getNumerator());
451         assertEquals(2, f.getDenominator());
452 
453         // normal
454         f = Fraction.getFraction(1, 1, 2);
455         assertEquals(3, f.getNumerator());
456         assertEquals(2, f.getDenominator());
457 
458         // negatives
459         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(1, -6, -10));
460         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(1, -6, -10));
461         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(1, -6, -10));
462 
463         // negative whole
464         f = Fraction.getFraction(-1, 6, 10);
465         assertEquals(-16, f.getNumerator());
466         assertEquals(10, f.getDenominator());
467 
468         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(-1, -6, 10));
469         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(-1, 6, -10));
470         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(-1, -6, -10));
471 
472         // zero denominator
473         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(0, 1, 0));
474         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(1, 2, 0));
475         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(-1, -3, 0));
476         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(Integer.MAX_VALUE, 1, 2));
477         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(-Integer.MAX_VALUE, 1, 2));
478 
479         // very large
480         f = Fraction.getFraction(-1, 0, Integer.MAX_VALUE);
481         assertEquals(-Integer.MAX_VALUE, f.getNumerator());
482         assertEquals(Integer.MAX_VALUE, f.getDenominator());
483 
484         // negative denominators not allowed in this constructor.
485         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(0, 4, Integer.MIN_VALUE));
486         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(1, 1, Integer.MAX_VALUE));
487         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(-1, 2, Integer.MAX_VALUE));
488     }
489 
490     @Test
491     void testFactory_String() {
492         assertNullPointerException(() -> Fraction.getFraction(null));
493     }
494 
495     @Test
496     void testFactory_String_double() {
497         Fraction f;
498 
499         f = Fraction.getFraction("0.0");
500         assertEquals(0, f.getNumerator());
501         assertEquals(1, f.getDenominator());
502 
503         f = Fraction.getFraction("0.2");
504         assertEquals(1, f.getNumerator());
505         assertEquals(5, f.getDenominator());
506 
507         f = Fraction.getFraction("0.5");
508         assertEquals(1, f.getNumerator());
509         assertEquals(2, f.getDenominator());
510 
511         f = Fraction.getFraction("0.66666");
512         assertEquals(2, f.getNumerator());
513         assertEquals(3, f.getDenominator());
514 
515         assertThrows(NumberFormatException.class, () -> Fraction.getFraction("2.3R"));
516         assertThrows(NumberFormatException.class, () -> Fraction.getFraction("2147483648")); // too big
517         assertThrows(NumberFormatException.class, () -> Fraction.getFraction("."));
518     }
519 
520     @Test
521     void testFactory_String_improper() {
522         Fraction f;
523 
524         f = Fraction.getFraction("0/1");
525         assertEquals(0, f.getNumerator());
526         assertEquals(1, f.getDenominator());
527 
528         f = Fraction.getFraction("1/5");
529         assertEquals(1, f.getNumerator());
530         assertEquals(5, f.getDenominator());
531 
532         f = Fraction.getFraction("1/2");
533         assertEquals(1, f.getNumerator());
534         assertEquals(2, f.getDenominator());
535 
536         f = Fraction.getFraction("2/3");
537         assertEquals(2, f.getNumerator());
538         assertEquals(3, f.getDenominator());
539 
540         f = Fraction.getFraction("7/3");
541         assertEquals(7, f.getNumerator());
542         assertEquals(3, f.getDenominator());
543 
544         f = Fraction.getFraction("2/4");
545         assertEquals(2, f.getNumerator());
546         assertEquals(4, f.getDenominator());
547 
548         assertThrows(NumberFormatException.class, () -> Fraction.getFraction("2/d"));
549         assertThrows(NumberFormatException.class, () -> Fraction.getFraction("2e/3"));
550         assertThrows(NumberFormatException.class, () -> Fraction.getFraction("2/"));
551         assertThrows(NumberFormatException.class, () -> Fraction.getFraction("/"));
552     }
553 
554     @Test
555     void testFactory_String_proper() {
556         Fraction f;
557 
558         f = Fraction.getFraction("0 0/1");
559         assertEquals(0, f.getNumerator());
560         assertEquals(1, f.getDenominator());
561 
562         f = Fraction.getFraction("1 1/5");
563         assertEquals(6, f.getNumerator());
564         assertEquals(5, f.getDenominator());
565 
566         f = Fraction.getFraction("7 1/2");
567         assertEquals(15, f.getNumerator());
568         assertEquals(2, f.getDenominator());
569 
570         f = Fraction.getFraction("1 2/4");
571         assertEquals(6, f.getNumerator());
572         assertEquals(4, f.getDenominator());
573 
574         f = Fraction.getFraction("-7 1/2");
575         assertEquals(-15, f.getNumerator());
576         assertEquals(2, f.getDenominator());
577 
578         f = Fraction.getFraction("-1 2/4");
579         assertEquals(-6, f.getNumerator());
580         assertEquals(4, f.getDenominator());
581 
582         assertThrows(NumberFormatException.class, () -> Fraction.getFraction("2 3"));
583         assertThrows(NumberFormatException.class, () -> Fraction.getFraction("a 3"));
584         assertThrows(NumberFormatException.class, () -> Fraction.getFraction("2 b/4"));
585         assertThrows(NumberFormatException.class, () -> Fraction.getFraction("2 "));
586         assertThrows(NumberFormatException.class, () -> Fraction.getFraction(" 3"));
587         assertThrows(NumberFormatException.class, () -> Fraction.getFraction(" "));
588     }
589 
590     @Test
591     void testGets() {
592         Fraction f;
593 
594         f = Fraction.getFraction(3, 5, 6);
595         assertEquals(23, f.getNumerator());
596         assertEquals(3, f.getProperWhole());
597         assertEquals(5, f.getProperNumerator());
598         assertEquals(6, f.getDenominator());
599 
600         f = Fraction.getFraction(-3, 5, 6);
601         assertEquals(-23, f.getNumerator());
602         assertEquals(-3, f.getProperWhole());
603         assertEquals(5, f.getProperNumerator());
604         assertEquals(6, f.getDenominator());
605 
606         f = Fraction.getFraction(Integer.MIN_VALUE, 0, 1);
607         assertEquals(Integer.MIN_VALUE, f.getNumerator());
608         assertEquals(Integer.MIN_VALUE, f.getProperWhole());
609         assertEquals(0, f.getProperNumerator());
610         assertEquals(1, f.getDenominator());
611     }
612 
613     @Test
614     void testHashCode() {
615         final Fraction f1 = Fraction.getFraction(3, 5);
616         Fraction f2 = Fraction.getFraction(3, 5);
617         assertEquals(f1.hashCode(), f2.hashCode());
618         f2 = Fraction.getFraction(2, 5);
619         assertTrue(f1.hashCode() != f2.hashCode());
620         f2 = Fraction.getFraction(6, 10);
621         assertTrue(f1.hashCode() != f2.hashCode());
622     }
623 
624     /**
625      * Tests https://issues.apache.org/jira/browse/LANG-1764
626      */
627     @ParameterizedTest
628     // @formatter:off
629     @CsvSource({
630         "0,          37,         -464320789,  46",
631         "0,          37,         -464320788,  9",
632         "0,          37,         1857283155,  38",
633         "0,          25185704,   1161454280,  1050304",
634         "0,          38817068,   1509581512,  18875972",
635         "0,          38817068,   -2146369536, 2145078572",
636         "1400217380, 128,        2092630052,  150535040",
637         "1400217380, 128,        -580400986,  268435638",
638         "1400217380, 2147483592, -2147483648, 268435452",
639         "1756395909, 4194598,    1174949894,  42860673"
640     })
641     // @formatter:on
642     void testHashCodeNotEquals(final int f1n, final int f1d, final int f2n, final int f2d) {
643         assertNotEquals(Fraction.getFraction(f1n, f1d), Fraction.getFraction(f2n, f2d));
644         assertNotEquals(Fraction.getFraction(f1n, f1d).hashCode(), Fraction.getFraction(f2n, f2d).hashCode());
645     }
646 
647     @Test
648     void testInvert() {
649         Fraction f;
650 
651         f = Fraction.getFraction(50, 75);
652         f = f.invert();
653         assertEquals(75, f.getNumerator());
654         assertEquals(50, f.getDenominator());
655 
656         f = Fraction.getFraction(4, 3);
657         f = f.invert();
658         assertEquals(3, f.getNumerator());
659         assertEquals(4, f.getDenominator());
660 
661         f = Fraction.getFraction(-15, 47);
662         f = f.invert();
663         assertEquals(-47, f.getNumerator());
664         assertEquals(15, f.getDenominator());
665 
666         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(0, 3).invert());
667         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(Integer.MIN_VALUE, 1).invert());
668 
669         f = Fraction.getFraction(Integer.MAX_VALUE, 1);
670         f = f.invert();
671         assertEquals(1, f.getNumerator());
672         assertEquals(Integer.MAX_VALUE, f.getDenominator());
673     }
674 
675     @Test
676     void testMultiply() {
677         Fraction f;
678         Fraction f1;
679         Fraction f2;
680 
681         f1 = Fraction.getFraction(3, 5);
682         f2 = Fraction.getFraction(2, 5);
683         f = f1.multiplyBy(f2);
684         assertEquals(6, f.getNumerator());
685         assertEquals(25, f.getDenominator());
686 
687         f1 = Fraction.getFraction(6, 10);
688         f2 = Fraction.getFraction(6, 10);
689         f = f1.multiplyBy(f2);
690         assertEquals(9, f.getNumerator());
691         assertEquals(25, f.getDenominator());
692         f = f.multiplyBy(f2);
693         assertEquals(27, f.getNumerator());
694         assertEquals(125, f.getDenominator());
695 
696         f1 = Fraction.getFraction(3, 5);
697         f2 = Fraction.getFraction(-2, 5);
698         f = f1.multiplyBy(f2);
699         assertEquals(-6, f.getNumerator());
700         assertEquals(25, f.getDenominator());
701 
702         f1 = Fraction.getFraction(-3, 5);
703         f2 = Fraction.getFraction(-2, 5);
704         f = f1.multiplyBy(f2);
705         assertEquals(6, f.getNumerator());
706         assertEquals(25, f.getDenominator());
707 
708         f1 = Fraction.getFraction(0, 5);
709         f2 = Fraction.getFraction(2, 7);
710         f = f1.multiplyBy(f2);
711         assertSame(Fraction.ZERO, f);
712 
713         f1 = Fraction.getFraction(2, 7);
714         f2 = Fraction.ONE;
715         f = f1.multiplyBy(f2);
716         assertEquals(2, f.getNumerator());
717         assertEquals(7, f.getDenominator());
718 
719         f1 = Fraction.getFraction(Integer.MAX_VALUE, 1);
720         f2 = Fraction.getFraction(Integer.MIN_VALUE, Integer.MAX_VALUE);
721         f = f1.multiplyBy(f2);
722         assertEquals(Integer.MIN_VALUE, f.getNumerator());
723         assertEquals(1, f.getDenominator());
724 
725         final Fraction fr = f;
726         assertNullPointerException(() -> fr.multiplyBy(null));
727 
728         final Fraction fr1 = Fraction.getFraction(1, Integer.MAX_VALUE);
729         assertThrows(ArithmeticException.class, () -> fr1.multiplyBy(fr1));
730 
731         final Fraction fr2 = Fraction.getFraction(1, -Integer.MAX_VALUE);
732         assertThrows(ArithmeticException.class, () -> fr2.multiplyBy(fr2));
733     }
734 
735     @Test
736     void testNegate() {
737         Fraction f;
738 
739         f = Fraction.getFraction(50, 75);
740         f = f.negate();
741         assertEquals(-50, f.getNumerator());
742         assertEquals(75, f.getDenominator());
743 
744         f = Fraction.getFraction(-50, 75);
745         f = f.negate();
746         assertEquals(50, f.getNumerator());
747         assertEquals(75, f.getDenominator());
748 
749         // large values
750         f = Fraction.getFraction(Integer.MAX_VALUE - 1, Integer.MAX_VALUE);
751         f = f.negate();
752         assertEquals(Integer.MIN_VALUE + 2, f.getNumerator());
753         assertEquals(Integer.MAX_VALUE, f.getDenominator());
754 
755         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(Integer.MIN_VALUE, 1).negate());
756     }
757 
758     @Test
759     void testPow() {
760         Fraction f;
761 
762         f = Fraction.getFraction(3, 5);
763         assertEquals(Fraction.ONE, f.pow(0));
764 
765         f = Fraction.getFraction(3, 5);
766         assertSame(f, f.pow(1));
767         assertEquals(f, f.pow(1));
768 
769         f = Fraction.getFraction(3, 5);
770         f = f.pow(2);
771         assertEquals(9, f.getNumerator());
772         assertEquals(25, f.getDenominator());
773 
774         f = Fraction.getFraction(3, 5);
775         f = f.pow(3);
776         assertEquals(27, f.getNumerator());
777         assertEquals(125, f.getDenominator());
778 
779         f = Fraction.getFraction(3, 5);
780         f = f.pow(-1);
781         assertEquals(5, f.getNumerator());
782         assertEquals(3, f.getDenominator());
783 
784         f = Fraction.getFraction(3, 5);
785         f = f.pow(-2);
786         assertEquals(25, f.getNumerator());
787         assertEquals(9, f.getDenominator());
788 
789         // check unreduced fractions stay that way.
790         f = Fraction.getFraction(6, 10);
791         assertEquals(Fraction.ONE, f.pow(0));
792 
793         f = Fraction.getFraction(6, 10);
794         assertEquals(f, f.pow(1));
795         assertNotEquals(f.pow(1), Fraction.getFraction(3, 5));
796 
797         f = Fraction.getFraction(6, 10);
798         f = f.pow(2);
799         assertEquals(9, f.getNumerator());
800         assertEquals(25, f.getDenominator());
801 
802         f = Fraction.getFraction(6, 10);
803         f = f.pow(3);
804         assertEquals(27, f.getNumerator());
805         assertEquals(125, f.getDenominator());
806 
807         f = Fraction.getFraction(6, 10);
808         f = f.pow(-1);
809         assertEquals(10, f.getNumerator());
810         assertEquals(6, f.getDenominator());
811 
812         f = Fraction.getFraction(6, 10);
813         f = f.pow(-2);
814         assertEquals(25, f.getNumerator());
815         assertEquals(9, f.getDenominator());
816 
817         // zero to any positive power is still zero.
818         f = Fraction.getFraction(0, 1231);
819         f = f.pow(1);
820         assertEquals(0, f.compareTo(Fraction.ZERO));
821         assertEquals(0, f.getNumerator());
822         assertEquals(1231, f.getDenominator());
823         f = f.pow(2);
824         assertEquals(0, f.compareTo(Fraction.ZERO));
825         assertEquals(0, f.getNumerator());
826         assertEquals(1, f.getDenominator());
827 
828         // zero to negative powers should throw an exception
829         final Fraction fr = f;
830         assertThrows(ArithmeticException.class, () -> fr.pow(-1));
831         assertThrows(ArithmeticException.class, () -> fr.pow(Integer.MIN_VALUE));
832 
833         // one to any power is still one.
834         f = Fraction.getFraction(1, 1);
835         f = f.pow(0);
836         assertEquals(f, Fraction.ONE);
837         f = f.pow(1);
838         assertEquals(f, Fraction.ONE);
839         f = f.pow(-1);
840         assertEquals(f, Fraction.ONE);
841         f = f.pow(Integer.MAX_VALUE);
842         assertEquals(f, Fraction.ONE);
843         f = f.pow(Integer.MIN_VALUE);
844         assertEquals(f, Fraction.ONE);
845 
846         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(Integer.MAX_VALUE, 1).pow(2));
847 
848         // Numerator growing too negative during the pow operation.
849         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(Integer.MIN_VALUE, 1).pow(3));
850 
851         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(65536, 1).pow(2));
852     }
853 
854     @Test
855     void testReduce() {
856         Fraction f;
857 
858         f = Fraction.getFraction(50, 75);
859         Fraction result = f.reduce();
860         assertEquals(2, result.getNumerator());
861         assertEquals(3, result.getDenominator());
862 
863         f = Fraction.getFraction(-2, -3);
864         result = f.reduce();
865         assertEquals(2, result.getNumerator());
866         assertEquals(3, result.getDenominator());
867 
868         f = Fraction.getFraction(2, -3);
869         result = f.reduce();
870         assertEquals(-2, result.getNumerator());
871         assertEquals(3, result.getDenominator());
872 
873         f = Fraction.getFraction(-2, 3);
874         result = f.reduce();
875         assertEquals(-2, result.getNumerator());
876         assertEquals(3, result.getDenominator());
877         assertSame(f, result);
878 
879         f = Fraction.getFraction(2, 3);
880         result = f.reduce();
881         assertEquals(2, result.getNumerator());
882         assertEquals(3, result.getDenominator());
883         assertSame(f, result);
884 
885         f = Fraction.getFraction(0, 1);
886         result = f.reduce();
887         assertEquals(0, result.getNumerator());
888         assertEquals(1, result.getDenominator());
889         assertSame(f, result);
890 
891         f = Fraction.getFraction(0, 100);
892         result = f.reduce();
893         assertEquals(0, result.getNumerator());
894         assertEquals(1, result.getDenominator());
895         assertSame(result, Fraction.ZERO);
896 
897         f = Fraction.getFraction(Integer.MIN_VALUE, 2);
898         result = f.reduce();
899         assertEquals(Integer.MIN_VALUE / 2, result.getNumerator());
900         assertEquals(1, result.getDenominator());
901     }
902 
903     @Test
904     void testReducedFactory_int_int() {
905         Fraction f;
906 
907         // zero
908         f = Fraction.getReducedFraction(0, 1);
909         assertEquals(0, f.getNumerator());
910         assertEquals(1, f.getDenominator());
911 
912         // normal
913         f = Fraction.getReducedFraction(1, 1);
914         assertEquals(1, f.getNumerator());
915         assertEquals(1, f.getDenominator());
916 
917         f = Fraction.getReducedFraction(2, 1);
918         assertEquals(2, f.getNumerator());
919         assertEquals(1, f.getDenominator());
920 
921         // improper
922         f = Fraction.getReducedFraction(22, 7);
923         assertEquals(22, f.getNumerator());
924         assertEquals(7, f.getDenominator());
925 
926         // negatives
927         f = Fraction.getReducedFraction(-6, 10);
928         assertEquals(-3, f.getNumerator());
929         assertEquals(5, f.getDenominator());
930 
931         f = Fraction.getReducedFraction(6, -10);
932         assertEquals(-3, f.getNumerator());
933         assertEquals(5, f.getDenominator());
934 
935         f = Fraction.getReducedFraction(-6, -10);
936         assertEquals(3, f.getNumerator());
937         assertEquals(5, f.getDenominator());
938 
939         // zero denominator
940         assertThrows(ArithmeticException.class, () -> Fraction.getReducedFraction(1, 0));
941         assertThrows(ArithmeticException.class, () -> Fraction.getReducedFraction(2, 0));
942         assertThrows(ArithmeticException.class, () -> Fraction.getReducedFraction(-3, 0));
943 
944         // reduced
945         f = Fraction.getReducedFraction(0, 2);
946         assertEquals(0, f.getNumerator());
947         assertEquals(1, f.getDenominator());
948 
949         f = Fraction.getReducedFraction(2, 2);
950         assertEquals(1, f.getNumerator());
951         assertEquals(1, f.getDenominator());
952 
953         f = Fraction.getReducedFraction(2, 4);
954         assertEquals(1, f.getNumerator());
955         assertEquals(2, f.getDenominator());
956 
957         f = Fraction.getReducedFraction(15, 10);
958         assertEquals(3, f.getNumerator());
959         assertEquals(2, f.getDenominator());
960 
961         f = Fraction.getReducedFraction(121, 22);
962         assertEquals(11, f.getNumerator());
963         assertEquals(2, f.getDenominator());
964 
965         // Extreme values
966         // OK, can reduce before negating
967         f = Fraction.getReducedFraction(-2, Integer.MIN_VALUE);
968         assertEquals(1, f.getNumerator());
969         assertEquals(-(Integer.MIN_VALUE / 2), f.getDenominator());
970 
971         // Can't reduce, negation will throw
972         assertThrows(ArithmeticException.class, () -> Fraction.getReducedFraction(-7, Integer.MIN_VALUE));
973 
974         // LANG-662
975         f = Fraction.getReducedFraction(Integer.MIN_VALUE, 2);
976         assertEquals(Integer.MIN_VALUE / 2, f.getNumerator());
977         assertEquals(1, f.getDenominator());
978     }
979 
980     @Test
981     void testSubtract() {
982         Fraction f;
983         Fraction f1;
984         Fraction f2;
985 
986         f1 = Fraction.getFraction(3, 5);
987         f2 = Fraction.getFraction(1, 5);
988         f = f1.subtract(f2);
989         assertEquals(2, f.getNumerator());
990         assertEquals(5, f.getDenominator());
991 
992         f1 = Fraction.getFraction(7, 5);
993         f2 = Fraction.getFraction(2, 5);
994         f = f1.subtract(f2);
995         assertEquals(1, f.getNumerator());
996         assertEquals(1, f.getDenominator());
997 
998         f1 = Fraction.getFraction(3, 5);
999         f2 = Fraction.getFraction(3, 5);
1000         f = f1.subtract(f2);
1001         assertEquals(0, f.getNumerator());
1002         assertEquals(1, f.getDenominator());
1003 
1004         f1 = Fraction.getFraction(3, 5);
1005         f2 = Fraction.getFraction(-4, 5);
1006         f = f1.subtract(f2);
1007         assertEquals(7, f.getNumerator());
1008         assertEquals(5, f.getDenominator());
1009 
1010         f1 = Fraction.getFraction(0, 5);
1011         f2 = Fraction.getFraction(4, 5);
1012         f = f1.subtract(f2);
1013         assertEquals(-4, f.getNumerator());
1014         assertEquals(5, f.getDenominator());
1015 
1016         f1 = Fraction.getFraction(0, 5);
1017         f2 = Fraction.getFraction(-4, 5);
1018         f = f1.subtract(f2);
1019         assertEquals(4, f.getNumerator());
1020         assertEquals(5, f.getDenominator());
1021 
1022         f1 = Fraction.getFraction(3, 5);
1023         f2 = Fraction.getFraction(1, 2);
1024         f = f1.subtract(f2);
1025         assertEquals(1, f.getNumerator());
1026         assertEquals(10, f.getDenominator());
1027 
1028         f1 = Fraction.getFraction(0, 5);
1029         f2 = Fraction.getFraction(1, 5);
1030         f = f2.subtract(f1);
1031         assertSame(f2, f);
1032 
1033         final Fraction fr = f;
1034         assertNullPointerException(() -> fr.subtract(null));
1035 
1036         // if this fraction is subtracted naively, it will overflow.
1037         // check that it doesn't.
1038         f1 = Fraction.getFraction(1, 32768 * 3);
1039         f2 = Fraction.getFraction(1, 59049);
1040         f = f1.subtract(f2);
1041         assertEquals(-13085, f.getNumerator());
1042         assertEquals(1934917632, f.getDenominator());
1043 
1044         f1 = Fraction.getFraction(Integer.MIN_VALUE, 3);
1045         f2 = Fraction.ONE_THIRD.negate();
1046         f = f1.subtract(f2);
1047         assertEquals(Integer.MIN_VALUE + 1, f.getNumerator());
1048         assertEquals(3, f.getDenominator());
1049 
1050         f1 = Fraction.getFraction(Integer.MAX_VALUE, 1);
1051         f2 = Fraction.ONE;
1052         f = f1.subtract(f2);
1053         assertEquals(Integer.MAX_VALUE - 1, f.getNumerator());
1054         assertEquals(1, f.getDenominator());
1055 
1056         // Should overflow
1057         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(1, Integer.MAX_VALUE).subtract(Fraction.getFraction(1, Integer.MAX_VALUE - 1)));
1058 
1059         // denominator should not be a multiple of 2 or 3 to trigger overflow
1060         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(Integer.MIN_VALUE, 5).subtract(Fraction.getFraction(1, 5)));
1061 
1062         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(Integer.MIN_VALUE, 1).subtract(Fraction.ONE));
1063 
1064         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(Integer.MAX_VALUE, 1).subtract(Fraction.ONE.negate()));
1065 
1066         // Should overflow
1067         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(3, 327680).subtract(Fraction.getFraction(2, 59049)));
1068     }
1069 
1070     @Test
1071     void testToProperString() {
1072         Fraction f;
1073 
1074         f = Fraction.getFraction(3, 5);
1075         final String str = f.toProperString();
1076         assertEquals("3/5", str);
1077         assertSame(str, f.toProperString());
1078 
1079         f = Fraction.getFraction(7, 5);
1080         assertEquals("1 2/5", f.toProperString());
1081 
1082         f = Fraction.getFraction(14, 10);
1083         assertEquals("1 4/10", f.toProperString());
1084 
1085         f = Fraction.getFraction(4, 2);
1086         assertEquals("2", f.toProperString());
1087 
1088         f = Fraction.getFraction(0, 2);
1089         assertEquals("0", f.toProperString());
1090 
1091         f = Fraction.getFraction(2, 2);
1092         assertEquals("1", f.toProperString());
1093 
1094         f = Fraction.getFraction(-7, 5);
1095         assertEquals("-1 2/5", f.toProperString());
1096 
1097         f = Fraction.getFraction(Integer.MIN_VALUE, 0, 1);
1098         assertEquals("-2147483648", f.toProperString());
1099 
1100         f = Fraction.getFraction(-1, 1, Integer.MAX_VALUE);
1101         assertEquals("-1 1/2147483647", f.toProperString());
1102 
1103         assertEquals("-1", Fraction.getFraction(-1).toProperString());
1104     }
1105 
1106     @Test
1107     void testToString() {
1108         Fraction f;
1109 
1110         f = Fraction.getFraction(3, 5);
1111         final String str = f.toString();
1112         assertEquals("3/5", str);
1113         assertSame(str, f.toString());
1114 
1115         f = Fraction.getFraction(7, 5);
1116         assertEquals("7/5", f.toString());
1117 
1118         f = Fraction.getFraction(4, 2);
1119         assertEquals("4/2", f.toString());
1120 
1121         f = Fraction.getFraction(0, 2);
1122         assertEquals("0/2", f.toString());
1123 
1124         f = Fraction.getFraction(2, 2);
1125         assertEquals("2/2", f.toString());
1126 
1127         f = Fraction.getFraction(Integer.MIN_VALUE, 0, 1);
1128         assertEquals("-2147483648/1", f.toString());
1129 
1130         f = Fraction.getFraction(-1, 1, Integer.MAX_VALUE);
1131         assertEquals("-2147483648/2147483647", f.toString());
1132     }
1133 }