1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.lang3.math;
18
19 import java.math.BigInteger;
20 import java.util.Objects;
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 public final class Fraction extends Number implements Comparable<Fraction> {
36
37
38
39
40
41
42 private static final long serialVersionUID = 65382027393090L;
43
44
45
46
47 public static final Fraction ZERO = new Fraction(0, 1);
48
49
50
51 public static final Fraction ONE = new Fraction(1, 1);
52
53
54
55 public static final Fraction ONE_HALF = new Fraction(1, 2);
56
57
58
59 public static final Fraction ONE_THIRD = new Fraction(1, 3);
60
61
62
63 public static final Fraction TWO_THIRDS = new Fraction(2, 3);
64
65
66
67 public static final Fraction ONE_QUARTER = new Fraction(1, 4);
68
69
70
71 public static final Fraction TWO_QUARTERS = new Fraction(2, 4);
72
73
74
75 public static final Fraction THREE_QUARTERS = new Fraction(3, 4);
76
77
78
79 public static final Fraction ONE_FIFTH = new Fraction(1, 5);
80
81
82
83 public static final Fraction TWO_FIFTHS = new Fraction(2, 5);
84
85
86
87 public static final Fraction THREE_FIFTHS = new Fraction(3, 5);
88
89
90
91 public static final Fraction FOUR_FIFTHS = new Fraction(4, 5);
92
93
94
95
96
97
98
99
100
101
102 private static int addAndCheck(final int x, final int y) {
103 final long s = (long) x + (long) y;
104 if (s < Integer.MIN_VALUE || s > Integer.MAX_VALUE) {
105 throw new ArithmeticException("overflow: add");
106 }
107 return (int) s;
108 }
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123 public static Fraction getFraction(double value) {
124 final int sign = value < 0 ? -1 : 1;
125 value = Math.abs(value);
126 if (value > Integer.MAX_VALUE || Double.isNaN(value)) {
127 throw new ArithmeticException("The value must not be greater than Integer.MAX_VALUE or NaN");
128 }
129 final int wholeNumber = (int) value;
130 value -= wholeNumber;
131
132 int numer0 = 0;
133 int denom0 = 1;
134 int numer1 = 1;
135 int denom1 = 0;
136 int numer2;
137 int denom2;
138 int a1 = (int) value;
139 int a2;
140 double x1 = 1;
141 double x2;
142 double y1 = value - a1;
143 double y2;
144 double delta1, delta2 = Double.MAX_VALUE;
145 double fraction;
146 int i = 1;
147 do {
148 delta1 = delta2;
149 a2 = (int) (x1 / y1);
150 x2 = y1;
151 y2 = x1 - a2 * y1;
152 numer2 = a1 * numer1 + numer0;
153 denom2 = a1 * denom1 + denom0;
154 fraction = (double) numer2 / (double) denom2;
155 delta2 = Math.abs(value - fraction);
156 a1 = a2;
157 x1 = x2;
158 y1 = y2;
159 numer0 = numer1;
160 denom0 = denom1;
161 numer1 = numer2;
162 denom1 = denom2;
163 i++;
164 } while (delta1 > delta2 && denom2 <= 10000 && denom2 > 0 && i < 25);
165 if (i == 25) {
166 throw new ArithmeticException("Unable to convert double to fraction");
167 }
168 return getReducedFraction((numer0 + wholeNumber * denom0) * sign, denom0);
169 }
170
171
172
173
174
175
176
177
178
179
180
181
182
183 public static Fraction getFraction(int numerator, int denominator) {
184 if (denominator == 0) {
185 throw new ArithmeticException("The denominator must not be zero");
186 }
187 if (denominator < 0) {
188 if (numerator == Integer.MIN_VALUE || denominator == Integer.MIN_VALUE) {
189 throw new ArithmeticException("overflow: can't negate");
190 }
191 numerator = -numerator;
192 denominator = -denominator;
193 }
194 return new Fraction(numerator, denominator);
195 }
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212 public static Fraction getFraction(final int whole, final int numerator, final int denominator) {
213 if (denominator == 0) {
214 throw new ArithmeticException("The denominator must not be zero");
215 }
216 if (denominator < 0) {
217 throw new ArithmeticException("The denominator must not be negative");
218 }
219 if (numerator < 0) {
220 throw new ArithmeticException("The numerator must not be negative");
221 }
222 final long numeratorValue;
223 if (whole < 0) {
224 numeratorValue = whole * (long) denominator - numerator;
225 } else {
226 numeratorValue = whole * (long) denominator + numerator;
227 }
228 if (numeratorValue < Integer.MIN_VALUE || numeratorValue > Integer.MAX_VALUE) {
229 throw new ArithmeticException("Numerator too large to represent as an Integer.");
230 }
231 return new Fraction((int) numeratorValue, denominator);
232 }
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251 public static Fraction getFraction(String str) {
252 Objects.requireNonNull(str, "str");
253
254 int pos = str.indexOf('.');
255 if (pos >= 0) {
256 return getFraction(Double.parseDouble(str));
257 }
258
259
260 pos = str.indexOf(' ');
261 if (pos > 0) {
262 final int whole = Integer.parseInt(str.substring(0, pos));
263 str = str.substring(pos + 1);
264 pos = str.indexOf('/');
265 if (pos < 0) {
266 throw new NumberFormatException("The fraction could not be parsed as the format X Y/Z");
267 }
268 final int numer = Integer.parseInt(str.substring(0, pos));
269 final int denom = Integer.parseInt(str.substring(pos + 1));
270 return getFraction(whole, numer, denom);
271 }
272
273
274 pos = str.indexOf('/');
275 if (pos < 0) {
276
277 return getFraction(Integer.parseInt(str), 1);
278 }
279 final int numer = Integer.parseInt(str.substring(0, pos));
280 final int denom = Integer.parseInt(str.substring(pos + 1));
281 return getFraction(numer, denom);
282 }
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298 public static Fraction getReducedFraction(int numerator, int denominator) {
299 if (denominator == 0) {
300 throw new ArithmeticException("The denominator must not be zero");
301 }
302 if (numerator == 0) {
303 return ZERO;
304 }
305
306 if (denominator == Integer.MIN_VALUE && (numerator & 1) == 0) {
307 numerator /= 2;
308 denominator /= 2;
309 }
310 if (denominator < 0) {
311 if (numerator == Integer.MIN_VALUE || denominator == Integer.MIN_VALUE) {
312 throw new ArithmeticException("overflow: can't negate");
313 }
314 numerator = -numerator;
315 denominator = -denominator;
316 }
317
318 final int gcd = greatestCommonDivisor(numerator, denominator);
319 numerator /= gcd;
320 denominator /= gcd;
321 return new Fraction(numerator, denominator);
322 }
323
324
325
326
327
328
329
330
331
332
333
334 private static int greatestCommonDivisor(int u, int v) {
335
336 if (u == 0 || v == 0) {
337 if (u == Integer.MIN_VALUE || v == Integer.MIN_VALUE) {
338 throw new ArithmeticException("overflow: gcd is 2^31");
339 }
340 return Math.abs(u) + Math.abs(v);
341 }
342
343 if (Math.abs(u) == 1 || Math.abs(v) == 1) {
344 return 1;
345 }
346
347
348
349
350 if (u > 0) {
351 u = -u;
352 }
353 if (v > 0) {
354 v = -v;
355 }
356
357 int k = 0;
358 while ((u & 1) == 0 && (v & 1) == 0 && k < 31) {
359 u /= 2;
360 v /= 2;
361 k++;
362 }
363 if (k == 31) {
364 throw new ArithmeticException("overflow: gcd is 2^31");
365 }
366
367
368 int t = (u & 1) == 1 ? v : -(u / 2);
369
370
371 do {
372
373
374 while ((t & 1) == 0) {
375 t /= 2;
376 }
377
378 if (t > 0) {
379 u = -t;
380 } else {
381 v = t;
382 }
383
384 t = (v - u) / 2;
385
386
387 } while (t != 0);
388 return -u * (1 << k);
389 }
390
391
392
393
394
395
396
397
398
399
400 private static int mulAndCheck(final int x, final int y) {
401 final long m = (long) x * (long) y;
402 if (m < Integer.MIN_VALUE || m > Integer.MAX_VALUE) {
403 throw new ArithmeticException("overflow: mul");
404 }
405 return (int) m;
406 }
407
408
409
410
411
412
413
414
415
416
417 private static int mulPosAndCheck(final int x, final int y) {
418
419 final long m = (long) x * (long) y;
420 if (m > Integer.MAX_VALUE) {
421 throw new ArithmeticException("overflow: mulPos");
422 }
423 return (int) m;
424 }
425
426
427
428
429
430
431
432
433
434
435 private static int subAndCheck(final int x, final int y) {
436 final long s = (long) x - (long) y;
437 if (s < Integer.MIN_VALUE || s > Integer.MAX_VALUE) {
438 throw new ArithmeticException("overflow: add");
439 }
440 return (int) s;
441 }
442
443
444
445
446 private final int numerator;
447
448
449
450
451 private final int denominator;
452
453
454
455
456 private transient int hashCode;
457
458
459
460
461 private transient String toString;
462
463
464
465
466 private transient String toProperString;
467
468
469
470
471
472
473
474
475 private Fraction(final int numerator, final int denominator) {
476 this.numerator = numerator;
477 this.denominator = denominator;
478 }
479
480
481
482
483
484
485
486
487
488
489 public Fraction abs() {
490 if (numerator >= 0) {
491 return this;
492 }
493 return negate();
494 }
495
496
497
498
499
500
501
502
503
504
505
506 public Fraction add(final Fraction fraction) {
507 return addSub(fraction, true );
508 }
509
510
511
512
513
514
515
516
517
518
519
520 private Fraction addSub(final Fraction fraction, final boolean isAdd) {
521 Objects.requireNonNull(fraction, "fraction");
522
523 if (numerator == 0) {
524 return isAdd ? fraction : fraction.negate();
525 }
526 if (fraction.numerator == 0) {
527 return this;
528 }
529
530
531 final int d1 = greatestCommonDivisor(denominator, fraction.denominator);
532 if (d1 == 1) {
533
534 final int uvp = mulAndCheck(numerator, fraction.denominator);
535 final int upv = mulAndCheck(fraction.numerator, denominator);
536 return new Fraction(isAdd ? addAndCheck(uvp, upv) : subAndCheck(uvp, upv), mulPosAndCheck(denominator,
537 fraction.denominator));
538 }
539
540
541
542 final BigInteger uvp = BigInteger.valueOf(numerator).multiply(BigInteger.valueOf(fraction.denominator / d1));
543 final BigInteger upv = BigInteger.valueOf(fraction.numerator).multiply(BigInteger.valueOf(denominator / d1));
544 final BigInteger t = isAdd ? uvp.add(upv) : uvp.subtract(upv);
545
546
547 final int tmodd1 = t.mod(BigInteger.valueOf(d1)).intValue();
548 final int d2 = tmodd1 == 0 ? d1 : greatestCommonDivisor(tmodd1, d1);
549
550
551 final BigInteger w = t.divide(BigInteger.valueOf(d2));
552 if (w.bitLength() > 31) {
553 throw new ArithmeticException("overflow: numerator too large after multiply");
554 }
555 return new Fraction(w.intValue(), mulPosAndCheck(denominator / d1, fraction.denominator / d2));
556 }
557
558
559
560
561
562
563
564
565
566
567
568
569
570 @Override
571 public int compareTo(final Fraction other) {
572 if (this == other) {
573 return 0;
574 }
575 if (numerator == other.numerator && denominator == other.denominator) {
576 return 0;
577 }
578
579
580 final long first = (long) numerator * (long) other.denominator;
581 final long second = (long) other.numerator * (long) denominator;
582 return Long.compare(first, second);
583 }
584
585
586
587
588
589
590
591
592
593
594
595 public Fraction divideBy(final Fraction fraction) {
596 Objects.requireNonNull(fraction, "fraction");
597 if (fraction.numerator == 0) {
598 throw new ArithmeticException("The fraction to divide by must not be zero");
599 }
600 return multiplyBy(fraction.invert());
601 }
602
603
604
605
606
607
608
609 @Override
610 public double doubleValue() {
611 return (double) numerator / (double) denominator;
612 }
613
614
615
616
617
618
619
620
621
622 @Override
623 public boolean equals(final Object obj) {
624 if (obj == this) {
625 return true;
626 }
627 if (!(obj instanceof Fraction)) {
628 return false;
629 }
630 final Fraction other = (Fraction) obj;
631 return getNumerator() == other.getNumerator() && getDenominator() == other.getDenominator();
632 }
633
634
635
636
637
638
639
640 @Override
641 public float floatValue() {
642 return (float) numerator / (float) denominator;
643 }
644
645
646
647
648
649
650 public int getDenominator() {
651 return denominator;
652 }
653
654
655
656
657
658
659
660
661
662 public int getNumerator() {
663 return numerator;
664 }
665
666
667
668
669
670
671
672
673
674
675
676
677 public int getProperNumerator() {
678 return Math.abs(numerator % denominator);
679 }
680
681
682
683
684
685
686
687
688
689
690
691
692 public int getProperWhole() {
693 return numerator / denominator;
694 }
695
696
697
698
699
700
701 @Override
702 public int hashCode() {
703 if (hashCode == 0) {
704
705 hashCode = 37 * (37 * 17 + getNumerator()) + getDenominator();
706 }
707 return hashCode;
708 }
709
710
711
712
713
714
715
716 @Override
717 public int intValue() {
718 return numerator / denominator;
719 }
720
721
722
723
724
725
726
727
728
729
730 public Fraction invert() {
731 if (numerator == 0) {
732 throw new ArithmeticException("Unable to invert zero.");
733 }
734 if (numerator == Integer.MIN_VALUE) {
735 throw new ArithmeticException("overflow: can't negate numerator");
736 }
737 if (numerator < 0) {
738 return new Fraction(-denominator, -numerator);
739 }
740 return new Fraction(denominator, numerator);
741 }
742
743
744
745
746
747
748
749 @Override
750 public long longValue() {
751 return (long) numerator / denominator;
752 }
753
754
755
756
757
758
759
760
761
762
763
764 public Fraction multiplyBy(final Fraction fraction) {
765 Objects.requireNonNull(fraction, "fraction");
766 if (numerator == 0 || fraction.numerator == 0) {
767 return ZERO;
768 }
769
770
771 final int d1 = greatestCommonDivisor(numerator, fraction.denominator);
772 final int d2 = greatestCommonDivisor(fraction.numerator, denominator);
773 return getReducedFraction(mulAndCheck(numerator / d1, fraction.numerator / d2), mulPosAndCheck(denominator / d2, fraction.denominator / d1));
774 }
775
776
777
778
779
780
781
782
783 public Fraction negate() {
784
785 if (numerator == Integer.MIN_VALUE) {
786 throw new ArithmeticException("overflow: too large to negate");
787 }
788 return new Fraction(-numerator, denominator);
789 }
790
791
792
793
794
795
796
797
798
799
800
801
802
803 public Fraction pow(final int power) {
804 if (power == 1) {
805 return this;
806 }
807 if (power == 0) {
808 return ONE;
809 }
810 if (power < 0) {
811 if (power == Integer.MIN_VALUE) {
812 return this.invert().pow(2).pow(-(power / 2));
813 }
814 return this.invert().pow(-power);
815 }
816 final Fraction f = this.multiplyBy(this);
817 if (power % 2 == 0) {
818 return f.pow(power / 2);
819 }
820 return f.pow(power / 2).multiplyBy(this);
821 }
822
823
824
825
826
827
828
829
830
831
832 public Fraction reduce() {
833 if (numerator == 0) {
834 return equals(ZERO) ? this : ZERO;
835 }
836 final int gcd = greatestCommonDivisor(Math.abs(numerator), denominator);
837 if (gcd == 1) {
838 return this;
839 }
840 return getFraction(numerator / gcd, denominator / gcd);
841 }
842
843
844
845
846
847
848
849
850
851
852
853 public Fraction subtract(final Fraction fraction) {
854 return addSub(fraction, false );
855 }
856
857
858
859
860
861
862
863
864
865
866 public String toProperString() {
867 if (toProperString == null) {
868 if (numerator == 0) {
869 toProperString = "0";
870 } else if (numerator == denominator) {
871 toProperString = "1";
872 } else if (numerator == -1 * denominator) {
873 toProperString = "-1";
874 } else if ((numerator > 0 ? -numerator : numerator) < -denominator) {
875
876
877
878
879 final int properNumerator = getProperNumerator();
880 if (properNumerator == 0) {
881 toProperString = Integer.toString(getProperWhole());
882 } else {
883 toProperString = getProperWhole() + " " + properNumerator + "/" + getDenominator();
884 }
885 } else {
886 toProperString = getNumerator() + "/" + getDenominator();
887 }
888 }
889 return toProperString;
890 }
891
892
893
894
895
896
897
898
899 @Override
900 public String toString() {
901 if (toString == null) {
902 toString = getNumerator() + "/" + getDenominator();
903 }
904 return toString;
905 }
906 }