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