View Javadoc
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| &gt; 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 &gt;= 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 }