1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.lang3.math;
18
19 import java.io.Serializable;
20 import java.math.BigInteger;
21 import java.util.Objects;
22
23 /**
24 * {@link Fraction} is a {@link Number} implementation that stores fractions accurately.
25 * <p>
26 * This class is immutable, and interoperable with most methods that accept a {@link Number}.
27 * </p>
28 * <p>
29 * Note that this class is intended for common use cases, it is <em>int</em> based and thus suffers from various overflow issues. For a BigInteger based
30 * equivalent, please see the Commons Math BigFraction class.
31 * </p>
32 *
33 * @since 2.0
34 */
35 public final class Fraction extends Number implements Comparable<Fraction> {
36
37 /**
38 * Required for serialization support. Lang version 2.0.
39 *
40 * @see Serializable
41 */
42 private static final long serialVersionUID = 65382027393090L;
43
44 /**
45 * {@link Fraction} representation of 0.
46 */
47 public static final Fraction ZERO = new Fraction(0, 1);
48
49 /**
50 * {@link Fraction} representation of 1.
51 */
52 public static final Fraction ONE = new Fraction(1, 1);
53
54 /**
55 * {@link Fraction} representation of 1/2.
56 */
57 public static final Fraction ONE_HALF = new Fraction(1, 2);
58
59 /**
60 * {@link Fraction} representation of 1/3.
61 */
62 public static final Fraction ONE_THIRD = new Fraction(1, 3);
63
64 /**
65 * {@link Fraction} representation of 2/3.
66 */
67 public static final Fraction TWO_THIRDS = new Fraction(2, 3);
68
69 /**
70 * {@link Fraction} representation of 1/4.
71 */
72 public static final Fraction ONE_QUARTER = new Fraction(1, 4);
73
74 /**
75 * {@link Fraction} representation of 2/4.
76 */
77 public static final Fraction TWO_QUARTERS = new Fraction(2, 4);
78
79 /**
80 * {@link Fraction} representation of 3/4.
81 */
82 public static final Fraction THREE_QUARTERS = new Fraction(3, 4);
83
84 /**
85 * {@link Fraction} representation of 1/5.
86 */
87 public static final Fraction ONE_FIFTH = new Fraction(1, 5);
88
89 /**
90 * {@link Fraction} representation of 2/5.
91 */
92 public static final Fraction TWO_FIFTHS = new Fraction(2, 5);
93
94 /**
95 * {@link Fraction} representation of 3/5.
96 */
97 public static final Fraction THREE_FIFTHS = new Fraction(3, 5);
98
99 /**
100 * {@link Fraction} representation of 4/5.
101 */
102 public static final Fraction FOUR_FIFTHS = new Fraction(4, 5);
103
104 /**
105 * Adds two integers, checking for overflow.
106 *
107 * @param x an addend
108 * @param y an addend
109 * @return the sum {@code x+y}
110 * @throws ArithmeticException if the result cannot be represented as
111 * an int
112 */
113 private static int addAndCheck(final int x, final int y) {
114 final long s = (long) x + (long) y;
115 if (s < Integer.MIN_VALUE || s > Integer.MAX_VALUE) {
116 throw new ArithmeticException("overflow: add");
117 }
118 return (int) s;
119 }
120
121 /**
122 * Creates a {@link Fraction} instance from a {@code double} value.
123 * <p>
124 * This method uses the <a href="https://web.archive.org/web/20210516065058/http%3A//archives.math.utk.edu/articles/atuyl/confrac/"> continued fraction
125 * algorithm</a>, computing a maximum of 25 convergents and bounding the denominator by 10,000.
126 * </p>
127 *
128 * @param value the double value to convert
129 * @return a new fraction instance that is close to the value
130 * @throws ArithmeticException if {@code |value| > Integer.MAX_VALUE} or {@code value = NaN}
131 * @throws ArithmeticException if the calculated denominator is {@code zero}
132 * @throws ArithmeticException if the algorithm does not converge
133 */
134 public static Fraction getFraction(double value) {
135 final int sign = value < 0 ? -1 : 1;
136 value = Math.abs(value);
137 if (value > Integer.MAX_VALUE || Double.isNaN(value)) {
138 throw new ArithmeticException("The value must not be greater than Integer.MAX_VALUE or NaN");
139 }
140 final int wholeNumber = (int) value;
141 value -= wholeNumber;
142 int numer0 = 0; // the pre-previous
143 int denom0 = 1; // the pre-previous
144 int numer1 = 1; // the previous
145 int denom1 = 0; // the previous
146 int numer2; // the current, setup in calculation
147 int denom2; // the current, setup in calculation
148 int a1 = (int) value;
149 int a2;
150 double x1 = 1;
151 double x2;
152 double y1 = value - a1;
153 double y2;
154 double delta1;
155 double delta2 = Double.MAX_VALUE;
156 double fraction;
157 int i = 1;
158 do {
159 delta1 = delta2;
160 a2 = (int) (x1 / y1);
161 x2 = y1;
162 y2 = x1 - a2 * y1;
163 numer2 = a1 * numer1 + numer0;
164 denom2 = a1 * denom1 + denom0;
165 fraction = (double) numer2 / (double) denom2;
166 delta2 = Math.abs(value - fraction);
167 a1 = a2;
168 x1 = x2;
169 y1 = y2;
170 numer0 = numer1;
171 denom0 = denom1;
172 numer1 = numer2;
173 denom1 = denom2;
174 i++;
175 } while (delta1 > delta2 && denom2 <= 10000 && denom2 > 0 && i < 25);
176 if (i == 25) {
177 throw new ArithmeticException("Unable to convert double to fraction");
178 }
179 return getReducedFraction((numer0 + wholeNumber * denom0) * sign, denom0);
180 }
181
182 /**
183 * Creates a {@link Fraction} instance with the 2 parts of a fraction Y/Z.
184 * <p>
185 * Any negative signs are resolved to be on the numerator.
186 * </p>
187 *
188 * @param numerator the numerator, for example the three in 'three sevenths'
189 * @param denominator the denominator, for example the seven in 'three sevenths'
190 * @return a new fraction instance
191 * @throws ArithmeticException if the denominator is {@code zero} or the denominator is {@code negative} and the numerator is {@code Integer#MIN_VALUE}
192 */
193 public static Fraction getFraction(int numerator, int denominator) {
194 if (denominator == 0) {
195 throw new ArithmeticException("The denominator must not be zero");
196 }
197 if (denominator < 0) {
198 if (numerator == Integer.MIN_VALUE || denominator == Integer.MIN_VALUE) {
199 throw new ArithmeticException("overflow: can't negate");
200 }
201 numerator = -numerator;
202 denominator = -denominator;
203 }
204 return new Fraction(numerator, denominator);
205 }
206
207 /**
208 * Creates a {@link Fraction} instance with the 3 parts of a fraction X Y/Z.
209 * <p>
210 * The negative sign must be passed in on the whole number part.
211 * </p>
212 *
213 * @param whole the whole number, for example the one in 'one and three sevenths'
214 * @param numerator the numerator, for example the three in 'one and three sevenths'
215 * @param denominator the denominator, for example the seven in 'one and three sevenths'
216 * @return a new fraction instance
217 * @throws ArithmeticException if the denominator is {@code zero}
218 * @throws ArithmeticException if the denominator is negative
219 * @throws ArithmeticException if the numerator is negative
220 * @throws ArithmeticException if the resulting numerator exceeds {@code Integer.MAX_VALUE}
221 */
222 public static Fraction getFraction(final int whole, final int numerator, final int denominator) {
223 if (denominator == 0) {
224 throw new ArithmeticException("The denominator must not be zero");
225 }
226 if (denominator < 0) {
227 throw new ArithmeticException("The denominator must not be negative");
228 }
229 if (numerator < 0) {
230 throw new ArithmeticException("The numerator must not be negative");
231 }
232 final long numeratorValue;
233 if (whole < 0) {
234 numeratorValue = whole * (long) denominator - numerator;
235 } else {
236 numeratorValue = whole * (long) denominator + numerator;
237 }
238 if (numeratorValue < Integer.MIN_VALUE || numeratorValue > Integer.MAX_VALUE) {
239 throw new ArithmeticException("Numerator too large to represent as an Integer.");
240 }
241 return new Fraction((int) numeratorValue, denominator);
242 }
243
244 /**
245 * Creates a Fraction from a {@link String}.
246 * <p>
247 * The formats accepted are:
248 * </p>
249 * <ol>
250 * <li>{@code double} String containing a dot</li>
251 * <li>'X Y/Z'</li>
252 * <li>'Y/Z'</li>
253 * <li>'X' (a simple whole number)</li>
254 * </ol>
255 * <p>
256 * and a .
257 * </p>
258 *
259 * @param str the string to parse, must not be {@code null}
260 * @return the new {@link Fraction} instance
261 * @throws NullPointerException if the string is {@code null}
262 * @throws NumberFormatException if the number format is invalid
263 */
264 public static Fraction getFraction(String str) {
265 Objects.requireNonNull(str, "str");
266 // parse double format
267 int pos = str.indexOf('.');
268 if (pos >= 0) {
269 return getFraction(Double.parseDouble(str));
270 }
271
272 // parse X Y/Z format
273 pos = str.indexOf(' ');
274 if (pos > 0) {
275 final int whole = Integer.parseInt(str.substring(0, pos));
276 str = str.substring(pos + 1);
277 pos = str.indexOf('/');
278 if (pos < 0) {
279 throw new NumberFormatException("The fraction could not be parsed as the format X Y/Z");
280 }
281 final int numer = Integer.parseInt(str.substring(0, pos));
282 final int denom = Integer.parseInt(str.substring(pos + 1));
283 return getFraction(whole, numer, denom);
284 }
285
286 // parse Y/Z format
287 pos = str.indexOf('/');
288 if (pos < 0) {
289 // simple whole number
290 return getFraction(Integer.parseInt(str), 1);
291 }
292 final int numer = Integer.parseInt(str.substring(0, pos));
293 final int denom = Integer.parseInt(str.substring(pos + 1));
294 return getFraction(numer, denom);
295 }
296
297 /**
298 * Creates a reduced {@link Fraction} instance with the 2 parts of a fraction Y/Z.
299 * <p>
300 * For example, if the input parameters represent 2/4, then the created fraction will be 1/2.
301 * </p>
302 *
303 * <p>
304 * Any negative signs are resolved to be on the numerator.
305 * </p>
306 *
307 * @param numerator the numerator, for example the three in 'three sevenths'
308 * @param denominator the denominator, for example the seven in 'three sevenths'
309 * @return a new fraction instance, with the numerator and denominator reduced
310 * @throws ArithmeticException if the denominator is {@code zero}
311 */
312 public static Fraction getReducedFraction(int numerator, int denominator) {
313 if (denominator == 0) {
314 throw new ArithmeticException("The denominator must not be zero");
315 }
316 if (numerator == 0) {
317 return ZERO; // normalize zero.
318 }
319 // allow 2^k/-2^31 as a valid fraction (where k>0)
320 if (denominator == Integer.MIN_VALUE && (numerator & 1) == 0) {
321 numerator /= 2;
322 denominator /= 2;
323 }
324 if (denominator < 0) {
325 if (numerator == Integer.MIN_VALUE || denominator == Integer.MIN_VALUE) {
326 throw new ArithmeticException("overflow: can't negate");
327 }
328 numerator = -numerator;
329 denominator = -denominator;
330 }
331 // simplify fraction.
332 final int gcd = greatestCommonDivisor(numerator, denominator);
333 numerator /= gcd;
334 denominator /= gcd;
335 return new Fraction(numerator, denominator);
336 }
337
338 /**
339 * Gets the greatest common divisor of the absolute value of
340 * two numbers, using the "binary gcd" method which avoids
341 * division and modulo operations. See Knuth 4.5.2 algorithm B.
342 * This algorithm is due to Josef Stein (1961).
343 *
344 * @param u a non-zero number
345 * @param v a non-zero number
346 * @return the greatest common divisor, never zero
347 */
348 private static int greatestCommonDivisor(int u, int v) {
349 // From Commons Math:
350 if (u == 0 || v == 0) {
351 if (u == Integer.MIN_VALUE || v == Integer.MIN_VALUE) {
352 throw new ArithmeticException("overflow: gcd is 2^31");
353 }
354 return Math.abs(u) + Math.abs(v);
355 }
356 // if either operand is abs 1, return 1:
357 if (Math.abs(u) == 1 || Math.abs(v) == 1) {
358 return 1;
359 }
360 // keep u and v negative, as negative integers range down to
361 // -2^31, while positive numbers can only be as large as 2^31-1
362 // (i.e. we can't necessarily negate a negative number without
363 // overflow)
364 if (u > 0) {
365 u = -u;
366 } // make u negative
367 if (v > 0) {
368 v = -v;
369 } // make v negative
370 // B1. [Find power of 2]
371 int k = 0;
372 while ((u & 1) == 0 && (v & 1) == 0 && k < 31) { // while u and v are both even...
373 u /= 2;
374 v /= 2;
375 k++; // cast out twos.
376 }
377 if (k == 31) {
378 throw new ArithmeticException("overflow: gcd is 2^31");
379 }
380 // B2. Initialize: u and v have been divided by 2^k and at least
381 // one is odd.
382 int t = (u & 1) == 1 ? v : -(u / 2)/* B3 */;
383 // t negative: u was odd, v may be even (t replaces v)
384 // t positive: u was even, v is odd (t replaces u)
385 do {
386 /* assert u<0 && v<0; */
387 // B4/B3: cast out twos from t.
388 while ((t & 1) == 0) { // while t is even.
389 t /= 2; // cast out twos
390 }
391 // B5 [reset max(u,v)]
392 if (t > 0) {
393 u = -t;
394 } else {
395 v = t;
396 }
397 // B6/B3. at this point both u and v should be odd.
398 t = (v - u) / 2;
399 // |u| larger: t positive (replace u)
400 // |v| larger: t negative (replace v)
401 } while (t != 0);
402 return -u * (1 << k); // gcd is u*2^k
403 }
404
405 /**
406 * Multiplies two integers, checking for overflow.
407 *
408 * @param x a factor
409 * @param y a factor
410 * @return the product {@code x*y}
411 * @throws ArithmeticException if the result cannot be represented as
412 * an int
413 */
414 private static int mulAndCheck(final int x, final int y) {
415 final long m = (long) x * (long) y;
416 if (m < Integer.MIN_VALUE || m > Integer.MAX_VALUE) {
417 throw new ArithmeticException("overflow: mul");
418 }
419 return (int) m;
420 }
421
422 /**
423 * Multiplies two non-negative integers, checking for overflow.
424 *
425 * @param x a non-negative factor
426 * @param y a non-negative factor
427 * @return the product {@code x*y}
428 * @throws ArithmeticException if the result cannot be represented as
429 * an int
430 */
431 private static int mulPosAndCheck(final int x, final int y) {
432 /* assert x>=0 && y>=0; */
433 final long m = (long) x * (long) y;
434 if (m > Integer.MAX_VALUE) {
435 throw new ArithmeticException("overflow: mulPos");
436 }
437 return (int) m;
438 }
439
440 /**
441 * Subtracts two integers, checking for overflow.
442 *
443 * @param x the minuend
444 * @param y the subtrahend
445 * @return the difference {@code x-y}
446 * @throws ArithmeticException if the result cannot be represented as
447 * an int
448 */
449 private static int subAndCheck(final int x, final int y) {
450 final long s = (long) x - (long) y;
451 if (s < Integer.MIN_VALUE || s > Integer.MAX_VALUE) {
452 throw new ArithmeticException("overflow: add");
453 }
454 return (int) s;
455 }
456
457 /**
458 * The numerator number part of the fraction (the three in three sevenths).
459 */
460 private final int numerator;
461
462 /**
463 * The denominator number part of the fraction (the seven in three sevenths).
464 */
465 private final int denominator;
466
467 /**
468 * Cached output hashCode (class is immutable).
469 */
470 private final int hashCode;
471
472 /**
473 * Cached output toString (class is immutable).
474 */
475 private transient String toString;
476
477 /**
478 * Cached output toProperString (class is immutable).
479 */
480 private transient String toProperString;
481
482 /**
483 * Constructs a {@link Fraction} instance with the 2 parts
484 * of a fraction Y/Z.
485 *
486 * @param numerator the numerator, for example the three in 'three sevenths'
487 * @param denominator the denominator, for example the seven in 'three sevenths'
488 */
489 private Fraction(final int numerator, final int denominator) {
490 this.numerator = numerator;
491 this.denominator = denominator;
492 this.hashCode = Objects.hash(denominator, numerator);
493 }
494
495 /**
496 * Gets a fraction that is the positive equivalent of this one.
497 * <p>
498 * More precisely: {@code (fraction >= 0 ? this : -fraction)}
499 * </p>
500 * <p>
501 * The returned fraction is not reduced.
502 * </p>
503 *
504 * @return {@code this} if it is positive, or a new positive fraction instance with the opposite signed numerator
505 */
506 public Fraction abs() {
507 if (numerator >= 0) {
508 return this;
509 }
510 return negate();
511 }
512
513 /**
514 * Adds the value of this fraction to another, returning the result in reduced form.
515 * The algorithm follows Knuth, 4.5.1.
516 *
517 * @param fraction the fraction to add, must not be {@code null}
518 * @return a {@link Fraction} instance with the resulting values
519 * @throws NullPointerException if the fraction is {@code null}
520 * @throws ArithmeticException if the resulting numerator or denominator exceeds
521 * {@code Integer.MAX_VALUE}
522 */
523 public Fraction add(final Fraction fraction) {
524 return addSub(fraction, true /* add */);
525 }
526
527 /**
528 * Implements add and subtract using the algorithm described in <a href="https://www-cs-faculty.stanford.edu/~knuth/taocp.html">
529 * The Art of Computer Programming (TAOCP)</a> 4.5.1 by Donald Knuth.
530 *
531 * @param fraction the fraction to subtract, must not be {@code null}
532 * @param isAdd true to add, false to subtract
533 * @return a {@link Fraction} instance with the resulting values
534 * @throws IllegalArgumentException if the fraction is {@code null}
535 * @throws ArithmeticException if the resulting numerator or denominator
536 * cannot be represented in an {@code int}.
537 */
538 private Fraction addSub(final Fraction fraction, final boolean isAdd) {
539 Objects.requireNonNull(fraction, "fraction");
540 // zero is identity for addition.
541 if (numerator == 0) {
542 return isAdd ? fraction : fraction.negate();
543 }
544 if (fraction.numerator == 0) {
545 return this;
546 }
547 // if denominators are randomly distributed, d1 will be 1 about 61%
548 // of the time.
549 final int d1 = greatestCommonDivisor(denominator, fraction.denominator);
550 if (d1 == 1) {
551 // result is ((u*v' +/- u'v) / u'v')
552 final int uvp = mulAndCheck(numerator, fraction.denominator);
553 final int upv = mulAndCheck(fraction.numerator, denominator);
554 return new Fraction(isAdd ? addAndCheck(uvp, upv) : subAndCheck(uvp, upv), mulPosAndCheck(denominator,
555 fraction.denominator));
556 }
557 // the quantity 't' requires 65 bits of precision; see knuth 4.5.1
558 // exercise 7. we're going to use a BigInteger.
559 // t = u(v'/d1) +/- v(u'/d1)
560 final BigInteger uvp = BigInteger.valueOf(numerator).multiply(BigInteger.valueOf(fraction.denominator / d1));
561 final BigInteger upv = BigInteger.valueOf(fraction.numerator).multiply(BigInteger.valueOf(denominator / d1));
562 final BigInteger t = isAdd ? uvp.add(upv) : uvp.subtract(upv);
563 // but d2 doesn't need extra precision because
564 // d2 = gcd(t,d1) = gcd(t mod d1, d1)
565 final int tmodd1 = t.mod(BigInteger.valueOf(d1)).intValue();
566 final int d2 = tmodd1 == 0 ? d1 : greatestCommonDivisor(tmodd1, d1);
567
568 // result is (t/d2) / (u'/d1)(v'/d2)
569 final BigInteger w = t.divide(BigInteger.valueOf(d2));
570 if (w.bitLength() > 31) {
571 throw new ArithmeticException("overflow: numerator too large after multiply");
572 }
573 return new Fraction(w.intValue(), mulPosAndCheck(denominator / d1, fraction.denominator / d2));
574 }
575
576 /**
577 * Compares this object to another based on size.
578 * <p>
579 * Note: this class has a natural ordering that is inconsistent with equals, because, for example, equals treats 1/2 and 2/4 as different, whereas compareTo
580 * treats them as equal.
581 * </p>
582 *
583 * @param other the object to compare to
584 * @return -1 if this is less, 0 if equal, +1 if greater
585 * @throws ClassCastException if the object is not a {@link Fraction}
586 * @throws NullPointerException if the object is {@code null}
587 */
588 @Override
589 public int compareTo(final Fraction other) {
590 if (this == other) {
591 return 0;
592 }
593 if (numerator == other.numerator && denominator == other.denominator) {
594 return 0;
595 }
596
597 // otherwise see which is less
598 final long first = (long) numerator * (long) other.denominator;
599 final long second = (long) other.numerator * (long) denominator;
600 return Long.compare(first, second);
601 }
602
603 /**
604 * Divide the value of this fraction by another.
605 *
606 * @param fraction the fraction to divide by, must not be {@code null}
607 * @return a {@link Fraction} instance with the resulting values
608 * @throws NullPointerException if the fraction is {@code null}
609 * @throws ArithmeticException if the fraction to divide by is zero
610 * @throws ArithmeticException if the resulting numerator or denominator exceeds
611 * {@code Integer.MAX_VALUE}
612 */
613 public Fraction divideBy(final Fraction fraction) {
614 Objects.requireNonNull(fraction, "fraction");
615 if (fraction.numerator == 0) {
616 throw new ArithmeticException("The fraction to divide by must not be zero");
617 }
618 return multiplyBy(fraction.invert());
619 }
620
621 /**
622 * Gets the fraction as a {@code double}. This calculates the fraction
623 * as the numerator divided by denominator.
624 *
625 * @return the fraction as a {@code double}
626 */
627 @Override
628 public double doubleValue() {
629 return (double) numerator / (double) denominator;
630 }
631
632 /**
633 * Compares this fraction to another object to test if they are equal.
634 * <p>
635 * To be equal, both values must be equal. Thus 2/4 is not equal to 1/2.
636 * </p>
637 *
638 * @param obj the reference object with which to compare
639 * @return {@code true} if this object is equal
640 */
641 @Override
642 public boolean equals(final Object obj) {
643 if (obj == this) {
644 return true;
645 }
646 if (!(obj instanceof Fraction)) {
647 return false;
648 }
649 final Fraction other = (Fraction) obj;
650 return getNumerator() == other.getNumerator() && getDenominator() == other.getDenominator();
651 }
652
653 /**
654 * Gets the fraction as a {@code float}. This calculates the fraction
655 * as the numerator divided by denominator.
656 *
657 * @return the fraction as a {@code float}
658 */
659 @Override
660 public float floatValue() {
661 return (float) numerator / (float) denominator;
662 }
663
664 /**
665 * Gets the denominator part of the fraction.
666 *
667 * @return the denominator fraction part
668 */
669 public int getDenominator() {
670 return denominator;
671 }
672
673 /**
674 * Gets the numerator part of the fraction.
675 * <p>
676 * This method may return a value greater than the denominator, an improper fraction, such as the seven in 7/4.
677 * </p>
678 *
679 * @return the numerator fraction part
680 */
681 public int getNumerator() {
682 return numerator;
683 }
684
685 /**
686 * Gets the proper numerator, always positive.
687 * <p>
688 * An improper fraction 7/4 can be resolved into a proper one, 1 3/4. This method returns the 3 from the proper fraction.
689 * </p>
690 *
691 * <p>
692 * If the fraction is negative such as -7/4, it can be resolved into -1 3/4, so this method returns the positive proper numerator, 3.
693 * </p>
694 *
695 * @return the numerator fraction part of a proper fraction, always positive
696 */
697 public int getProperNumerator() {
698 return Math.abs(numerator % denominator);
699 }
700
701 /**
702 * Gets the proper whole part of the fraction.
703 * <p>
704 * An improper fraction 7/4 can be resolved into a proper one, 1 3/4. This method returns the 1 from the proper fraction.
705 * </p>
706 *
707 * <p>
708 * If the fraction is negative such as -7/4, it can be resolved into -1 3/4, so this method returns the positive whole part -1.
709 * </p>
710 *
711 * @return the whole fraction part of a proper fraction, that includes the sign
712 */
713 public int getProperWhole() {
714 return numerator / denominator;
715 }
716
717 /**
718 * Gets a hashCode for the fraction.
719 *
720 * @return a hash code value for this object
721 */
722 @Override
723 public int hashCode() {
724 return hashCode;
725 }
726
727 /**
728 * Gets the fraction as an {@code int}. This returns the whole number
729 * part of the fraction.
730 *
731 * @return the whole number fraction part
732 */
733 @Override
734 public int intValue() {
735 return numerator / denominator;
736 }
737
738 /**
739 * Gets a fraction that is the inverse (1/fraction) of this one.
740 * <p>
741 * The returned fraction is not reduced.
742 * </p>
743 *
744 * @return a new fraction instance with the numerator and denominator inverted.
745 * @throws ArithmeticException if the fraction represents zero.
746 */
747 public Fraction invert() {
748 if (numerator == 0) {
749 throw new ArithmeticException("Unable to invert zero.");
750 }
751 if (numerator == Integer.MIN_VALUE) {
752 throw new ArithmeticException("overflow: can't negate numerator");
753 }
754 if (numerator < 0) {
755 return new Fraction(-denominator, -numerator);
756 }
757 return new Fraction(denominator, numerator);
758 }
759
760 /**
761 * Gets the fraction as a {@code long}. This returns the whole number
762 * part of the fraction.
763 *
764 * @return the whole number fraction part
765 */
766 @Override
767 public long longValue() {
768 return (long) numerator / denominator;
769 }
770
771 /**
772 * Multiplies the value of this fraction by another, returning the
773 * result in reduced form.
774 *
775 * @param fraction the fraction to multiply by, must not be {@code null}
776 * @return a {@link Fraction} instance with the resulting values
777 * @throws NullPointerException if the fraction is {@code null}
778 * @throws ArithmeticException if the resulting numerator or denominator exceeds
779 * {@code Integer.MAX_VALUE}
780 */
781 public Fraction multiplyBy(final Fraction fraction) {
782 Objects.requireNonNull(fraction, "fraction");
783 if (numerator == 0 || fraction.numerator == 0) {
784 return ZERO;
785 }
786 // knuth 4.5.1
787 // make sure we don't overflow unless the result *must* overflow.
788 final int d1 = greatestCommonDivisor(numerator, fraction.denominator);
789 final int d2 = greatestCommonDivisor(fraction.numerator, denominator);
790 return getReducedFraction(mulAndCheck(numerator / d1, fraction.numerator / d2), mulPosAndCheck(denominator / d2, fraction.denominator / d1));
791 }
792
793 /**
794 * Gets a fraction that is the negative (-fraction) of this one.
795 * <p>
796 * The returned fraction is not reduced.
797 * </p>
798 *
799 * @return a new fraction instance with the opposite signed numerator
800 */
801 public Fraction negate() {
802 // the positive range is one smaller than the negative range of an int.
803 if (numerator == Integer.MIN_VALUE) {
804 throw new ArithmeticException("overflow: too large to negate");
805 }
806 return new Fraction(-numerator, denominator);
807 }
808
809 /**
810 * Gets a fraction that is raised to the passed in power.
811 * <p>
812 * The returned fraction is in reduced form.
813 * </p>
814 *
815 * @param power the power to raise the fraction to
816 * @return {@code this} if the power is one, {@link #ONE} if the power is zero (even if the fraction equals ZERO) or a new fraction instance raised to the
817 * appropriate power
818 * @throws ArithmeticException if the resulting numerator or denominator exceeds {@code Integer.MAX_VALUE}
819 */
820 public Fraction pow(final int power) {
821 if (power == 1) {
822 return this;
823 }
824 if (power == 0) {
825 return ONE;
826 }
827 if (power < 0) {
828 if (power == Integer.MIN_VALUE) { // MIN_VALUE can't be negated.
829 return invert().pow(2).pow(-(power / 2));
830 }
831 return invert().pow(-power);
832 }
833 final Fraction f = multiplyBy(this);
834 if (power % 2 == 0) { // if even...
835 return f.pow(power / 2);
836 }
837 return f.pow(power / 2).multiplyBy(this);
838 }
839
840 /**
841 * Reduce the fraction to the smallest values for the numerator and denominator, returning the result.
842 * <p>
843 * For example, if this fraction represents 2/4, then the result will be 1/2.
844 * </p>
845 *
846 * @return a new reduced fraction instance, or this if no simplification possible
847 */
848 public Fraction reduce() {
849 if (numerator == 0) {
850 return equals(ZERO) ? this : ZERO;
851 }
852 final int gcd = greatestCommonDivisor(Math.abs(numerator), denominator);
853 if (gcd == 1) {
854 return this;
855 }
856 return getFraction(numerator / gcd, denominator / gcd);
857 }
858
859 /**
860 * Subtracts the value of another fraction from the value of this one,
861 * returning the result in reduced form.
862 *
863 * @param fraction the fraction to subtract, must not be {@code null}
864 * @return a {@link Fraction} instance with the resulting values
865 * @throws NullPointerException if the fraction is {@code null}
866 * @throws ArithmeticException if the resulting numerator or denominator
867 * cannot be represented in an {@code int}.
868 */
869 public Fraction subtract(final Fraction fraction) {
870 return addSub(fraction, false /* subtract */);
871 }
872
873 /**
874 * Gets the fraction as a proper {@link String} in the format X Y/Z.
875 * <p>
876 * The format used in '<em>wholeNumber</em> <em>numerator</em>/<em>denominator</em>'. If the whole number is zero it will be omitted. If the numerator is
877 * zero, only the whole number is returned.
878 * </p>
879 *
880 * @return a {@link String} form of the fraction
881 */
882 public String toProperString() {
883 if (toProperString == null) {
884 if (numerator == 0) {
885 toProperString = "0";
886 } else if (numerator == denominator) {
887 toProperString = "1";
888 } else if (numerator == -1 * denominator) {
889 toProperString = "-1";
890 } else if ((numerator > 0 ? -numerator : numerator) < -denominator) {
891 // note that we do the magnitude comparison test above with
892 // NEGATIVE (not positive) numbers, since negative numbers
893 // have a larger range. otherwise numerator == Integer.MIN_VALUE
894 // is handled incorrectly.
895 final int properNumerator = getProperNumerator();
896 if (properNumerator == 0) {
897 toProperString = Integer.toString(getProperWhole());
898 } else {
899 toProperString = getProperWhole() + " " + properNumerator + "/" + getDenominator();
900 }
901 } else {
902 toProperString = getNumerator() + "/" + getDenominator();
903 }
904 }
905 return toProperString;
906 }
907
908 /**
909 * Gets the fraction as a {@link String}.
910 * <p>
911 * The format used is '<em>numerator</em>/<em>denominator</em>' always.
912 * </p>
913 *
914 * @return a {@link String} form of the fraction
915 */
916 @Override
917 public String toString() {
918 if (toString == null) {
919 toString = getNumerator() + "/" + getDenominator();
920 }
921 return toString;
922 }
923 }