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   * http://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.junit.jupiter.api.Assertions.assertEquals;
22  import static org.junit.jupiter.api.Assertions.assertNotEquals;
23  import static org.junit.jupiter.api.Assertions.assertSame;
24  import static org.junit.jupiter.api.Assertions.assertThrows;
25  import static org.junit.jupiter.api.Assertions.assertTrue;
26  
27  import org.apache.commons.lang3.AbstractLangTest;
28  import org.junit.jupiter.api.Test;
29  
30  /**
31   * Test cases for the {@link Fraction} class
32   */
33  public class FractionTest extends AbstractLangTest {
34  
35      private static final int SKIP = 500;  //53
36  
37      @Test
38      public void testAbs() {
39          Fraction f;
40  
41          f = Fraction.getFraction(50, 75);
42          f = f.abs();
43          assertEquals(50, f.getNumerator());
44          assertEquals(75, f.getDenominator());
45  
46          f = Fraction.getFraction(-50, 75);
47          f = f.abs();
48          assertEquals(50, f.getNumerator());
49          assertEquals(75, f.getDenominator());
50  
51          f = Fraction.getFraction(Integer.MAX_VALUE, 1);
52          f = f.abs();
53          assertEquals(Integer.MAX_VALUE, f.getNumerator());
54          assertEquals(1, f.getDenominator());
55  
56          f = Fraction.getFraction(Integer.MAX_VALUE, -1);
57          f = f.abs();
58          assertEquals(Integer.MAX_VALUE, f.getNumerator());
59          assertEquals(1, f.getDenominator());
60  
61          assertThrows(ArithmeticException.class, () -> Fraction.getFraction(Integer.MIN_VALUE, 1).abs());
62      }
63  
64      @Test
65      public void testAdd() {
66          Fraction f;
67          Fraction f1;
68          Fraction f2;
69  
70          f1 = Fraction.getFraction(3, 5);
71          f2 = Fraction.getFraction(1, 5);
72          f = f1.add(f2);
73          assertEquals(4, f.getNumerator());
74          assertEquals(5, f.getDenominator());
75  
76          f1 = Fraction.getFraction(3, 5);
77          f2 = Fraction.getFraction(2, 5);
78          f = f1.add(f2);
79          assertEquals(1, f.getNumerator());
80          assertEquals(1, f.getDenominator());
81  
82          f1 = Fraction.getFraction(3, 5);
83          f2 = Fraction.getFraction(3, 5);
84          f = f1.add(f2);
85          assertEquals(6, f.getNumerator());
86          assertEquals(5, f.getDenominator());
87  
88          f1 = Fraction.getFraction(3, 5);
89          f2 = Fraction.getFraction(-4, 5);
90          f = f1.add(f2);
91          assertEquals(-1, f.getNumerator());
92          assertEquals(5, f.getDenominator());
93  
94          f1 = Fraction.getFraction(Integer.MAX_VALUE - 1, 1);
95          f2 = Fraction.ONE;
96          f = f1.add(f2);
97          assertEquals(Integer.MAX_VALUE, f.getNumerator());
98          assertEquals(1, f.getDenominator());
99  
100         f1 = Fraction.getFraction(3, 5);
101         f2 = Fraction.getFraction(1, 2);
102         f = f1.add(f2);
103         assertEquals(11, f.getNumerator());
104         assertEquals(10, f.getDenominator());
105 
106         f1 = Fraction.getFraction(3, 8);
107         f2 = Fraction.getFraction(1, 6);
108         f = f1.add(f2);
109         assertEquals(13, f.getNumerator());
110         assertEquals(24, f.getDenominator());
111 
112         f1 = Fraction.getFraction(0, 5);
113         f2 = Fraction.getFraction(1, 5);
114         f = f1.add(f2);
115         assertSame(f2, f);
116         f = f2.add(f1);
117         assertSame(f2, f);
118 
119         f1 = Fraction.getFraction(-1, 13*13*2*2);
120         f2 = Fraction.getFraction(-2, 13*17*2);
121         final Fraction fr = f1.add(f2);
122         assertEquals(13*13*17*2*2, fr.getDenominator());
123         assertEquals(-17 - 2*13*2, fr.getNumerator());
124 
125         assertThrows(NullPointerException.class, () -> fr.add(null));
126 
127         // if this fraction is added naively, it will overflow.
128         // check that it doesn't.
129         f1 = Fraction.getFraction(1, 32768*3);
130         f2 = Fraction.getFraction(1, 59049);
131         f = f1.add(f2);
132         assertEquals(52451, f.getNumerator());
133         assertEquals(1934917632, f.getDenominator());
134 
135         f1 = Fraction.getFraction(Integer.MIN_VALUE, 3);
136         f2 = Fraction.ONE_THIRD;
137         f = f1.add(f2);
138         assertEquals(Integer.MIN_VALUE+1, f.getNumerator());
139         assertEquals(3, f.getDenominator());
140 
141         f1 = Fraction.getFraction(Integer.MAX_VALUE - 1, 1);
142         f2 = Fraction.ONE;
143         f = f1.add(f2);
144         assertEquals(Integer.MAX_VALUE, f.getNumerator());
145         assertEquals(1, f.getDenominator());
146 
147         final Fraction overflower = f;
148         assertThrows(ArithmeticException.class, () -> overflower.add(Fraction.ONE)); // should overflow
149 
150         // denominator should not be a multiple of 2 or 3 to trigger overflow
151         assertThrows(
152                 ArithmeticException.class,
153                 () -> Fraction.getFraction(Integer.MIN_VALUE, 5).add(Fraction.getFraction(-1, 5)));
154 
155         final Fraction maxValue = Fraction.getFraction(-Integer.MAX_VALUE, 1);
156         assertThrows(ArithmeticException.class, () -> maxValue.add(maxValue));
157 
158         final Fraction negativeMaxValue = Fraction.getFraction(-Integer.MAX_VALUE, 1);
159         assertThrows(ArithmeticException.class, () -> negativeMaxValue.add(negativeMaxValue));
160 
161         final Fraction f3 = Fraction.getFraction(3, 327680);
162         final Fraction f4 = Fraction.getFraction(2, 59049);
163         assertThrows(ArithmeticException.class, () -> f3.add(f4)); // should overflow
164     }
165 
166     @Test
167     public void testCompareTo() {
168         final Fraction f1;
169         Fraction f2;
170 
171         f1 = Fraction.getFraction(3, 5);
172         assertEquals(0, f1.compareTo(f1));
173 
174         final Fraction fr = f1;
175         assertThrows(NullPointerException.class, () -> fr.compareTo(null));
176 
177         f2 = Fraction.getFraction(2, 5);
178         assertTrue(f1.compareTo(f2) > 0);
179         assertEquals(0, f2.compareTo(f2));
180 
181         f2 = Fraction.getFraction(4, 5);
182         assertTrue(f1.compareTo(f2) < 0);
183         assertEquals(0, f2.compareTo(f2));
184 
185         f2 = Fraction.getFraction(3, 5);
186         assertEquals(0, f1.compareTo(f2));
187         assertEquals(0, f2.compareTo(f2));
188 
189         f2 = Fraction.getFraction(6, 10);
190         assertEquals(0, f1.compareTo(f2));
191         assertEquals(0, f2.compareTo(f2));
192 
193         f2 = Fraction.getFraction(-1, 1, Integer.MAX_VALUE);
194         assertTrue(f1.compareTo(f2) > 0);
195         assertEquals(0, f2.compareTo(f2));
196 
197     }
198 
199     @Test
200     public void testConstants() {
201         assertEquals(0, Fraction.ZERO.getNumerator());
202         assertEquals(1, Fraction.ZERO.getDenominator());
203 
204         assertEquals(1, Fraction.ONE.getNumerator());
205         assertEquals(1, Fraction.ONE.getDenominator());
206 
207         assertEquals(1, Fraction.ONE_HALF.getNumerator());
208         assertEquals(2, Fraction.ONE_HALF.getDenominator());
209 
210         assertEquals(1, Fraction.ONE_THIRD.getNumerator());
211         assertEquals(3, Fraction.ONE_THIRD.getDenominator());
212 
213         assertEquals(2, Fraction.TWO_THIRDS.getNumerator());
214         assertEquals(3, Fraction.TWO_THIRDS.getDenominator());
215 
216         assertEquals(1, Fraction.ONE_QUARTER.getNumerator());
217         assertEquals(4, Fraction.ONE_QUARTER.getDenominator());
218 
219         assertEquals(2, Fraction.TWO_QUARTERS.getNumerator());
220         assertEquals(4, Fraction.TWO_QUARTERS.getDenominator());
221 
222         assertEquals(3, Fraction.THREE_QUARTERS.getNumerator());
223         assertEquals(4, Fraction.THREE_QUARTERS.getDenominator());
224 
225         assertEquals(1, Fraction.ONE_FIFTH.getNumerator());
226         assertEquals(5, Fraction.ONE_FIFTH.getDenominator());
227 
228         assertEquals(2, Fraction.TWO_FIFTHS.getNumerator());
229         assertEquals(5, Fraction.TWO_FIFTHS.getDenominator());
230 
231         assertEquals(3, Fraction.THREE_FIFTHS.getNumerator());
232         assertEquals(5, Fraction.THREE_FIFTHS.getDenominator());
233 
234         assertEquals(4, Fraction.FOUR_FIFTHS.getNumerator());
235         assertEquals(5, Fraction.FOUR_FIFTHS.getDenominator());
236     }
237 
238     @Test
239     public void testConversions() {
240         final Fraction f;
241 
242         f = Fraction.getFraction(3, 7, 8);
243         assertEquals(3, f.intValue());
244         assertEquals(3L, f.longValue());
245         assertEquals(3.875f, f.floatValue(), 0.00001f);
246         assertEquals(3.875d, f.doubleValue(), 0.00001d);
247     }
248 
249     @Test
250     public void testDivide() {
251         Fraction f;
252         Fraction f1;
253         Fraction f2;
254 
255         f1 = Fraction.getFraction(3, 5);
256         f2 = Fraction.getFraction(2, 5);
257         f = f1.divideBy(f2);
258         assertEquals(3, f.getNumerator());
259         assertEquals(2, f.getDenominator());
260 
261         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(3, 5).divideBy(Fraction.ZERO));
262 
263         f1 = Fraction.getFraction(0, 5);
264         f2 = Fraction.getFraction(2, 7);
265         f = f1.divideBy(f2);
266         assertSame(Fraction.ZERO, f);
267 
268         f1 = Fraction.getFraction(2, 7);
269         f2 = Fraction.ONE;
270         f = f1.divideBy(f2);
271         assertEquals(2, f.getNumerator());
272         assertEquals(7, f.getDenominator());
273 
274         f1 = Fraction.getFraction(1, Integer.MAX_VALUE);
275         f = f1.divideBy(f1);
276         assertEquals(1, f.getNumerator());
277         assertEquals(1, f.getDenominator());
278 
279         f1 = Fraction.getFraction(Integer.MIN_VALUE, Integer.MAX_VALUE);
280         f2 = Fraction.getFraction(1, Integer.MAX_VALUE);
281         final Fraction fr = f1.divideBy(f2);
282         assertEquals(Integer.MIN_VALUE, fr.getNumerator());
283         assertEquals(1, fr.getDenominator());
284 
285         assertThrows(NullPointerException.class, () -> fr.divideBy(null));
286 
287         final Fraction smallest = Fraction.getFraction(1, Integer.MAX_VALUE);
288         assertThrows(ArithmeticException.class, () -> smallest.divideBy(smallest.invert())); // Should overflow
289 
290         final Fraction negative = Fraction.getFraction(1, -Integer.MAX_VALUE);
291         assertThrows(ArithmeticException.class, () -> negative.divideBy(negative.invert())); // Should overflow
292     }
293 
294 
295     @Test
296     public 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     public 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 = null;
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     public 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     public 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     public void testFactory_String() {
492         assertThrows(NullPointerException.class, () -> Fraction.getFraction(null));
493     }
494 
495     @Test
496     public 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     public 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     public 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     public 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     public void testHashCode() {
615         final Fraction f1 = Fraction.getFraction(3, 5);
616         Fraction f2 = Fraction.getFraction(3, 5);
617 
618         assertEquals(f1.hashCode(), f2.hashCode());
619 
620         f2 = Fraction.getFraction(2, 5);
621         assertTrue(f1.hashCode() != f2.hashCode());
622 
623         f2 = Fraction.getFraction(6, 10);
624         assertTrue(f1.hashCode() != f2.hashCode());
625     }
626 
627     @Test
628     public void testInvert() {
629         Fraction f;
630 
631         f = Fraction.getFraction(50, 75);
632         f = f.invert();
633         assertEquals(75, f.getNumerator());
634         assertEquals(50, f.getDenominator());
635 
636         f = Fraction.getFraction(4, 3);
637         f = f.invert();
638         assertEquals(3, f.getNumerator());
639         assertEquals(4, f.getDenominator());
640 
641         f = Fraction.getFraction(-15, 47);
642         f = f.invert();
643         assertEquals(-47, f.getNumerator());
644         assertEquals(15, f.getDenominator());
645 
646         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(0, 3).invert());
647         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(Integer.MIN_VALUE, 1).invert());
648 
649         f = Fraction.getFraction(Integer.MAX_VALUE, 1);
650         f = f.invert();
651         assertEquals(1, f.getNumerator());
652         assertEquals(Integer.MAX_VALUE, f.getDenominator());
653     }
654 
655     @Test
656     public void testMultiply() {
657         Fraction f;
658         Fraction f1;
659         Fraction f2;
660 
661         f1 = Fraction.getFraction(3, 5);
662         f2 = Fraction.getFraction(2, 5);
663         f = f1.multiplyBy(f2);
664         assertEquals(6, f.getNumerator());
665         assertEquals(25, f.getDenominator());
666 
667         f1 = Fraction.getFraction(6, 10);
668         f2 = Fraction.getFraction(6, 10);
669         f = f1.multiplyBy(f2);
670         assertEquals(9, f.getNumerator());
671         assertEquals(25, f.getDenominator());
672         f = f.multiplyBy(f2);
673         assertEquals(27, f.getNumerator());
674         assertEquals(125, f.getDenominator());
675 
676         f1 = Fraction.getFraction(3, 5);
677         f2 = Fraction.getFraction(-2, 5);
678         f = f1.multiplyBy(f2);
679         assertEquals(-6, f.getNumerator());
680         assertEquals(25, f.getDenominator());
681 
682         f1 = Fraction.getFraction(-3, 5);
683         f2 = Fraction.getFraction(-2, 5);
684         f = f1.multiplyBy(f2);
685         assertEquals(6, f.getNumerator());
686         assertEquals(25, f.getDenominator());
687 
688 
689         f1 = Fraction.getFraction(0, 5);
690         f2 = Fraction.getFraction(2, 7);
691         f = f1.multiplyBy(f2);
692         assertSame(Fraction.ZERO, f);
693 
694         f1 = Fraction.getFraction(2, 7);
695         f2 = Fraction.ONE;
696         f = f1.multiplyBy(f2);
697         assertEquals(2, f.getNumerator());
698         assertEquals(7, f.getDenominator());
699 
700         f1 = Fraction.getFraction(Integer.MAX_VALUE, 1);
701         f2 = Fraction.getFraction(Integer.MIN_VALUE, Integer.MAX_VALUE);
702         f = f1.multiplyBy(f2);
703         assertEquals(Integer.MIN_VALUE, f.getNumerator());
704         assertEquals(1, f.getDenominator());
705 
706         final Fraction fr = f;
707         assertThrows(NullPointerException.class, () -> fr.multiplyBy(null));
708 
709         final Fraction fr1 = Fraction.getFraction(1, Integer.MAX_VALUE);
710         assertThrows(ArithmeticException.class, () -> fr1.multiplyBy(fr1));
711 
712         final Fraction fr2 = Fraction.getFraction(1, -Integer.MAX_VALUE);
713         assertThrows(ArithmeticException.class, () -> fr2.multiplyBy(fr2));
714     }
715 
716     @Test
717     public void testNegate() {
718         Fraction f;
719 
720         f = Fraction.getFraction(50, 75);
721         f = f.negate();
722         assertEquals(-50, f.getNumerator());
723         assertEquals(75, f.getDenominator());
724 
725         f = Fraction.getFraction(-50, 75);
726         f = f.negate();
727         assertEquals(50, f.getNumerator());
728         assertEquals(75, f.getDenominator());
729 
730         // large values
731         f = Fraction.getFraction(Integer.MAX_VALUE-1, Integer.MAX_VALUE);
732         f = f.negate();
733         assertEquals(Integer.MIN_VALUE+2, f.getNumerator());
734         assertEquals(Integer.MAX_VALUE, f.getDenominator());
735 
736         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(Integer.MIN_VALUE, 1).negate());
737     }
738 
739     @Test
740     public void testPow() {
741         Fraction f;
742 
743         f = Fraction.getFraction(3, 5);
744         assertEquals(Fraction.ONE, f.pow(0));
745 
746         f = Fraction.getFraction(3, 5);
747         assertSame(f, f.pow(1));
748         assertEquals(f, f.pow(1));
749 
750         f = Fraction.getFraction(3, 5);
751         f = f.pow(2);
752         assertEquals(9, f.getNumerator());
753         assertEquals(25, f.getDenominator());
754 
755         f = Fraction.getFraction(3, 5);
756         f = f.pow(3);
757         assertEquals(27, f.getNumerator());
758         assertEquals(125, f.getDenominator());
759 
760         f = Fraction.getFraction(3, 5);
761         f = f.pow(-1);
762         assertEquals(5, f.getNumerator());
763         assertEquals(3, f.getDenominator());
764 
765         f = Fraction.getFraction(3, 5);
766         f = f.pow(-2);
767         assertEquals(25, f.getNumerator());
768         assertEquals(9, f.getDenominator());
769 
770         // check unreduced fractions stay that way.
771         f = Fraction.getFraction(6, 10);
772         assertEquals(Fraction.ONE, f.pow(0));
773 
774         f = Fraction.getFraction(6, 10);
775         assertEquals(f, f.pow(1));
776         assertNotEquals(f.pow(1), Fraction.getFraction(3, 5));
777 
778         f = Fraction.getFraction(6, 10);
779         f = f.pow(2);
780         assertEquals(9, f.getNumerator());
781         assertEquals(25, f.getDenominator());
782 
783         f = Fraction.getFraction(6, 10);
784         f = f.pow(3);
785         assertEquals(27, f.getNumerator());
786         assertEquals(125, f.getDenominator());
787 
788         f = Fraction.getFraction(6, 10);
789         f = f.pow(-1);
790         assertEquals(10, f.getNumerator());
791         assertEquals(6, f.getDenominator());
792 
793         f = Fraction.getFraction(6, 10);
794         f = f.pow(-2);
795         assertEquals(25, f.getNumerator());
796         assertEquals(9, f.getDenominator());
797 
798         // zero to any positive power is still zero.
799         f = Fraction.getFraction(0, 1231);
800         f = f.pow(1);
801         assertEquals(0, f.compareTo(Fraction.ZERO));
802         assertEquals(0, f.getNumerator());
803         assertEquals(1231, f.getDenominator());
804         f = f.pow(2);
805         assertEquals(0, f.compareTo(Fraction.ZERO));
806         assertEquals(0, f.getNumerator());
807         assertEquals(1, f.getDenominator());
808 
809         // zero to negative powers should throw an exception
810         final Fraction fr = f;
811         assertThrows(ArithmeticException.class, () -> fr.pow(-1));
812         assertThrows(ArithmeticException.class, () -> fr.pow(Integer.MIN_VALUE));
813 
814         // one to any power is still one.
815         f = Fraction.getFraction(1, 1);
816         f = f.pow(0);
817         assertEquals(f, Fraction.ONE);
818         f = f.pow(1);
819         assertEquals(f, Fraction.ONE);
820         f = f.pow(-1);
821         assertEquals(f, Fraction.ONE);
822         f = f.pow(Integer.MAX_VALUE);
823         assertEquals(f, Fraction.ONE);
824         f = f.pow(Integer.MIN_VALUE);
825         assertEquals(f, Fraction.ONE);
826 
827         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(Integer.MAX_VALUE, 1).pow(2));
828 
829         // Numerator growing too negative during the pow operation.
830         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(Integer.MIN_VALUE, 1).pow(3));
831 
832         assertThrows(ArithmeticException.class, () -> Fraction.getFraction(65536, 1).pow(2));
833     }
834 
835     @Test
836     public void testReduce() {
837         Fraction f;
838 
839         f = Fraction.getFraction(50, 75);
840         Fraction result = f.reduce();
841         assertEquals(2, result.getNumerator());
842         assertEquals(3, result.getDenominator());
843 
844         f = Fraction.getFraction(-2, -3);
845         result = f.reduce();
846         assertEquals(2, result.getNumerator());
847         assertEquals(3, result.getDenominator());
848 
849         f = Fraction.getFraction(2, -3);
850         result = f.reduce();
851         assertEquals(-2, result.getNumerator());
852         assertEquals(3, result.getDenominator());
853 
854         f = Fraction.getFraction(-2, 3);
855         result = f.reduce();
856         assertEquals(-2, result.getNumerator());
857         assertEquals(3, result.getDenominator());
858         assertSame(f, result);
859 
860         f = Fraction.getFraction(2, 3);
861         result = f.reduce();
862         assertEquals(2, result.getNumerator());
863         assertEquals(3, result.getDenominator());
864         assertSame(f, result);
865 
866         f = Fraction.getFraction(0, 1);
867         result = f.reduce();
868         assertEquals(0, result.getNumerator());
869         assertEquals(1, result.getDenominator());
870         assertSame(f, result);
871 
872         f = Fraction.getFraction(0, 100);
873         result = f.reduce();
874         assertEquals(0, result.getNumerator());
875         assertEquals(1, result.getDenominator());
876         assertSame(result, Fraction.ZERO);
877 
878         f = Fraction.getFraction(Integer.MIN_VALUE, 2);
879         result = f.reduce();
880         assertEquals(Integer.MIN_VALUE / 2, result.getNumerator());
881         assertEquals(1, result.getDenominator());
882     }
883 
884     @Test
885     public void testReducedFactory_int_int() {
886         Fraction f;
887 
888         // zero
889         f = Fraction.getReducedFraction(0, 1);
890         assertEquals(0, f.getNumerator());
891         assertEquals(1, f.getDenominator());
892 
893         // normal
894         f = Fraction.getReducedFraction(1, 1);
895         assertEquals(1, f.getNumerator());
896         assertEquals(1, f.getDenominator());
897 
898         f = Fraction.getReducedFraction(2, 1);
899         assertEquals(2, f.getNumerator());
900         assertEquals(1, f.getDenominator());
901 
902         // improper
903         f = Fraction.getReducedFraction(22, 7);
904         assertEquals(22, f.getNumerator());
905         assertEquals(7, f.getDenominator());
906 
907         // negatives
908         f = Fraction.getReducedFraction(-6, 10);
909         assertEquals(-3, f.getNumerator());
910         assertEquals(5, f.getDenominator());
911 
912         f = Fraction.getReducedFraction(6, -10);
913         assertEquals(-3, f.getNumerator());
914         assertEquals(5, f.getDenominator());
915 
916         f = Fraction.getReducedFraction(-6, -10);
917         assertEquals(3, f.getNumerator());
918         assertEquals(5, f.getDenominator());
919 
920         // zero denominator
921         assertThrows(ArithmeticException.class, () -> Fraction.getReducedFraction(1, 0));
922         assertThrows(ArithmeticException.class, () -> Fraction.getReducedFraction(2, 0));
923         assertThrows(ArithmeticException.class, () -> Fraction.getReducedFraction(-3, 0));
924 
925         // reduced
926         f = Fraction.getReducedFraction(0, 2);
927         assertEquals(0, f.getNumerator());
928         assertEquals(1, f.getDenominator());
929 
930         f = Fraction.getReducedFraction(2, 2);
931         assertEquals(1, f.getNumerator());
932         assertEquals(1, f.getDenominator());
933 
934         f = Fraction.getReducedFraction(2, 4);
935         assertEquals(1, f.getNumerator());
936         assertEquals(2, f.getDenominator());
937 
938         f = Fraction.getReducedFraction(15, 10);
939         assertEquals(3, f.getNumerator());
940         assertEquals(2, f.getDenominator());
941 
942         f = Fraction.getReducedFraction(121, 22);
943         assertEquals(11, f.getNumerator());
944         assertEquals(2, f.getDenominator());
945 
946         // Extreme values
947         // OK, can reduce before negating
948         f = Fraction.getReducedFraction(-2, Integer.MIN_VALUE);
949         assertEquals(1, f.getNumerator());
950         assertEquals(-(Integer.MIN_VALUE / 2), f.getDenominator());
951 
952         // Can't reduce, negation will throw
953         assertThrows(ArithmeticException.class, () -> Fraction.getReducedFraction(-7, Integer.MIN_VALUE));
954 
955         // LANG-662
956         f = Fraction.getReducedFraction(Integer.MIN_VALUE, 2);
957         assertEquals(Integer.MIN_VALUE / 2, f.getNumerator());
958         assertEquals(1, f.getDenominator());
959     }
960 
961     @Test
962     public void testSubtract() {
963         Fraction f;
964         Fraction f1;
965         Fraction f2;
966 
967         f1 = Fraction.getFraction(3, 5);
968         f2 = Fraction.getFraction(1, 5);
969         f = f1.subtract(f2);
970         assertEquals(2, f.getNumerator());
971         assertEquals(5, f.getDenominator());
972 
973         f1 = Fraction.getFraction(7, 5);
974         f2 = Fraction.getFraction(2, 5);
975         f = f1.subtract(f2);
976         assertEquals(1, f.getNumerator());
977         assertEquals(1, f.getDenominator());
978 
979         f1 = Fraction.getFraction(3, 5);
980         f2 = Fraction.getFraction(3, 5);
981         f = f1.subtract(f2);
982         assertEquals(0, f.getNumerator());
983         assertEquals(1, f.getDenominator());
984 
985         f1 = Fraction.getFraction(3, 5);
986         f2 = Fraction.getFraction(-4, 5);
987         f = f1.subtract(f2);
988         assertEquals(7, f.getNumerator());
989         assertEquals(5, f.getDenominator());
990 
991         f1 = Fraction.getFraction(0, 5);
992         f2 = Fraction.getFraction(4, 5);
993         f = f1.subtract(f2);
994         assertEquals(-4, f.getNumerator());
995         assertEquals(5, f.getDenominator());
996 
997         f1 = Fraction.getFraction(0, 5);
998         f2 = Fraction.getFraction(-4, 5);
999         f = f1.subtract(f2);
1000         assertEquals(4, f.getNumerator());
1001         assertEquals(5, f.getDenominator());
1002 
1003         f1 = Fraction.getFraction(3, 5);
1004         f2 = Fraction.getFraction(1, 2);
1005         f = f1.subtract(f2);
1006         assertEquals(1, f.getNumerator());
1007         assertEquals(10, f.getDenominator());
1008 
1009         f1 = Fraction.getFraction(0, 5);
1010         f2 = Fraction.getFraction(1, 5);
1011         f = f2.subtract(f1);
1012         assertSame(f2, f);
1013 
1014         final Fraction fr = f;
1015         assertThrows(NullPointerException.class, () -> fr.subtract(null));
1016 
1017         // if this fraction is subtracted naively, it will overflow.
1018         // check that it doesn't.
1019         f1 = Fraction.getFraction(1, 32768*3);
1020         f2 = Fraction.getFraction(1, 59049);
1021         f = f1.subtract(f2);
1022         assertEquals(-13085, f.getNumerator());
1023         assertEquals(1934917632, f.getDenominator());
1024 
1025         f1 = Fraction.getFraction(Integer.MIN_VALUE, 3);
1026         f2 = Fraction.ONE_THIRD.negate();
1027         f = f1.subtract(f2);
1028         assertEquals(Integer.MIN_VALUE+1, f.getNumerator());
1029         assertEquals(3, f.getDenominator());
1030 
1031         f1 = Fraction.getFraction(Integer.MAX_VALUE, 1);
1032         f2 = Fraction.ONE;
1033         f = f1.subtract(f2);
1034         assertEquals(Integer.MAX_VALUE-1, f.getNumerator());
1035         assertEquals(1, f.getDenominator());
1036 
1037         // Should overflow
1038         assertThrows(
1039                 ArithmeticException.class,
1040                 () -> Fraction.getFraction(1, Integer.MAX_VALUE).subtract(Fraction.getFraction(1, Integer.MAX_VALUE - 1)));
1041             f = f1.subtract(f2);
1042 
1043         // denominator should not be a multiple of 2 or 3 to trigger overflow
1044         assertThrows(
1045                 ArithmeticException.class,
1046                 () -> Fraction.getFraction(Integer.MIN_VALUE, 5).subtract(Fraction.getFraction(1, 5)));
1047 
1048         assertThrows(
1049                 ArithmeticException.class, () -> Fraction.getFraction(Integer.MIN_VALUE, 1).subtract(Fraction.ONE));
1050 
1051         assertThrows(
1052                 ArithmeticException.class,
1053                 () -> Fraction.getFraction(Integer.MAX_VALUE, 1).subtract(Fraction.ONE.negate()));
1054 
1055         // Should overflow
1056         assertThrows(
1057                 ArithmeticException.class,
1058                 () -> Fraction.getFraction(3, 327680).subtract(Fraction.getFraction(2, 59049)));
1059     }
1060 
1061     @Test
1062     public void testToProperString() {
1063         Fraction f;
1064 
1065         f = Fraction.getFraction(3, 5);
1066         final String str = f.toProperString();
1067         assertEquals("3/5", str);
1068         assertSame(str, f.toProperString());
1069 
1070         f = Fraction.getFraction(7, 5);
1071         assertEquals("1 2/5", f.toProperString());
1072 
1073         f = Fraction.getFraction(14, 10);
1074         assertEquals("1 4/10", f.toProperString());
1075 
1076         f = Fraction.getFraction(4, 2);
1077         assertEquals("2", f.toProperString());
1078 
1079         f = Fraction.getFraction(0, 2);
1080         assertEquals("0", f.toProperString());
1081 
1082         f = Fraction.getFraction(2, 2);
1083         assertEquals("1", f.toProperString());
1084 
1085         f = Fraction.getFraction(-7, 5);
1086         assertEquals("-1 2/5", f.toProperString());
1087 
1088         f = Fraction.getFraction(Integer.MIN_VALUE, 0, 1);
1089         assertEquals("-2147483648", f.toProperString());
1090 
1091         f = Fraction.getFraction(-1, 1, Integer.MAX_VALUE);
1092         assertEquals("-1 1/2147483647", f.toProperString());
1093 
1094         assertEquals("-1", Fraction.getFraction(-1).toProperString());
1095     }
1096 
1097     @Test
1098     public void testToString() {
1099         Fraction f;
1100 
1101         f = Fraction.getFraction(3, 5);
1102         final String str = f.toString();
1103         assertEquals("3/5", str);
1104         assertSame(str, f.toString());
1105 
1106         f = Fraction.getFraction(7, 5);
1107         assertEquals("7/5", f.toString());
1108 
1109         f = Fraction.getFraction(4, 2);
1110         assertEquals("4/2", f.toString());
1111 
1112         f = Fraction.getFraction(0, 2);
1113         assertEquals("0/2", f.toString());
1114 
1115         f = Fraction.getFraction(2, 2);
1116         assertEquals("2/2", f.toString());
1117 
1118         f = Fraction.getFraction(Integer.MIN_VALUE, 0, 1);
1119         assertEquals("-2147483648/1", f.toString());
1120 
1121         f = Fraction.getFraction(-1, 1, Integer.MAX_VALUE);
1122         assertEquals("-2147483648/2147483647", f.toString());
1123     }
1124 }