001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      https://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.lang3.math;
018
019import java.io.IOException;
020import java.io.InvalidObjectException;
021import java.io.ObjectInputStream;
022import java.io.Serializable;
023import java.math.BigInteger;
024import java.util.Objects;
025
026/**
027 * {@link Fraction} is a {@link Number} implementation that stores fractions accurately.
028 * <p>
029 * This class is immutable, and interoperable with most methods that accept a {@link Number}.
030 * </p>
031 * <p>
032 * 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
033 * equivalent, please see the Commons Math BigFraction class.
034 * </p>
035 *
036 * @since 2.0
037 */
038public final class Fraction extends Number implements Comparable<Fraction> {
039
040    /**
041     * Required for serialization support. Lang version 2.0.
042     *
043     * @see Serializable
044     */
045    private static final long serialVersionUID = 65382027393090L;
046
047    /**
048     * {@link Fraction} representation of 0.
049     */
050    public static final Fraction ZERO = new Fraction(0, 1);
051
052    /**
053     * {@link Fraction} representation of 1.
054     */
055    public static final Fraction ONE = new Fraction(1, 1);
056
057    /**
058     * {@link Fraction} representation of 1/2.
059     */
060    public static final Fraction ONE_HALF = new Fraction(1, 2);
061
062    /**
063     * {@link Fraction} representation of 1/3.
064     */
065    public static final Fraction ONE_THIRD = new Fraction(1, 3);
066
067    /**
068     * {@link Fraction} representation of 2/3.
069     */
070    public static final Fraction TWO_THIRDS = new Fraction(2, 3);
071
072    /**
073     * {@link Fraction} representation of 1/4.
074     */
075    public static final Fraction ONE_QUARTER = new Fraction(1, 4);
076
077    /**
078     * {@link Fraction} representation of 2/4.
079     */
080    public static final Fraction TWO_QUARTERS = new Fraction(2, 4);
081
082    /**
083     * {@link Fraction} representation of 3/4.
084     */
085    public static final Fraction THREE_QUARTERS = new Fraction(3, 4);
086
087    /**
088     * {@link Fraction} representation of 1/5.
089     */
090    public static final Fraction ONE_FIFTH = new Fraction(1, 5);
091
092    /**
093     * {@link Fraction} representation of 2/5.
094     */
095    public static final Fraction TWO_FIFTHS = new Fraction(2, 5);
096
097    /**
098     * {@link Fraction} representation of 3/5.
099     */
100    public static final Fraction THREE_FIFTHS = new Fraction(3, 5);
101
102    /**
103     * {@link Fraction} representation of 4/5.
104     */
105    public static final Fraction FOUR_FIFTHS = new Fraction(4, 5);
106
107    /**
108     * Checks that a denominator is not zero.
109     *
110     * @param denominator The denominator to check
111     * @throws ArithmeticException Thrown if the denominator is zero.
112     */
113    private static void checkDenominator(final int denominator) {
114        if (denominator == 0) {
115            throw new ArithmeticException("The denominator must not be zero");
116        }
117    }
118
119    /**
120     * Gets a {@link Fraction} instance from a {@code double} value.
121     * <p>
122     * This method uses the <a href="https://web.archive.org/web/20210516065058/http%3A//archives.math.utk.edu/articles/atuyl/confrac/"> continued fraction
123     * algorithm</a>, computing a maximum of 25 convergents and bounding the denominator by 10,000.
124     * </p>
125     *
126     * @param value The double value to convert
127     * @return A new fraction instance that is close to the value
128     * @throws ArithmeticException Thrown if {@code |value| &gt; Integer.MAX_VALUE} or {@code value = NaN}.
129     * @throws ArithmeticException Thrown if the calculated denominator is {@code zero}.
130     * @throws ArithmeticException Thrown if the algorithm does not converge.
131     */
132    public static Fraction getFraction(double value) {
133        final int sign = value < 0 ? -1 : 1;
134        value = Math.abs(value);
135        if (value > Integer.MAX_VALUE || Double.isNaN(value)) {
136            throw new ArithmeticException("The value must not be greater than Integer.MAX_VALUE or NaN");
137        }
138        final int wholeNumber = (int) value;
139        value -= wholeNumber;
140        int numer0 = 0; // the pre-previous
141        int denom0 = 1; // the pre-previous
142        int numer1 = 1; // the previous
143        int denom1 = 0; // the previous
144        int numer2; // the current, setup in calculation
145        int denom2; // the current, setup in calculation
146        int a1 = (int) value;
147        int a2;
148        double x1 = 1;
149        double x2;
150        double y1 = value - a1;
151        double y2;
152        double delta1;
153        double delta2 = Double.MAX_VALUE;
154        double fraction;
155        int i = 1;
156        do {
157            delta1 = delta2;
158            a2 = (int) (x1 / y1);
159            x2 = y1;
160            y2 = x1 - a2 * y1;
161            numer2 = a1 * numer1 + numer0;
162            denom2 = a1 * denom1 + denom0;
163            fraction = (double) numer2 / (double) denom2;
164            delta2 = Math.abs(value - fraction);
165            a1 = a2;
166            x1 = x2;
167            y1 = y2;
168            numer0 = numer1;
169            denom0 = denom1;
170            numer1 = numer2;
171            denom1 = denom2;
172            i++;
173        } while (delta1 > delta2 && denom2 <= 10000 && denom2 > 0 && i < 25);
174        if (i == 25) {
175            throw new ArithmeticException("Unable to convert double to fraction");
176        }
177        // wholeNumber can be up to Integer.MAX_VALUE while denom0 > 1 for any non-integer value,
178        // so the int product overflows for values near the limit; check it instead of wrapping silently.
179        final int numerator = Math.addExact(numer0, mulAndCheck(wholeNumber, denom0));
180        return getReducedFraction(numerator * sign, denom0);
181    }
182
183    /**
184     * Gets a {@link Fraction} instance with the 2 parts of a fraction Y/Z.
185     * <p>
186     * Any negative signs are resolved to be on the numerator.
187     * </p>
188     *
189     * @param numerator   The numerator, for example the three in 'three sevenths'
190     * @param denominator The denominator, for example the seven in 'three sevenths'
191     * @return A new fraction instance
192     * @throws ArithmeticException Thrown if the denominator is {@code zero} or the denominator is {@code negative} and the numerator is
193     *         {@code Integer#MIN_VALUE}.
194     */
195    public static Fraction getFraction(int numerator, int denominator) {
196        checkDenominator(denominator);
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     * Gets 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 Thrown if the denominator is {@code zero}.
218     * @throws ArithmeticException Thrown if the denominator is negative.
219     * @throws ArithmeticException Thrown if the numerator is negative.
220     * @throws ArithmeticException Thrown 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        checkDenominator(denominator);
224        if (denominator < 0) {
225            throw new ArithmeticException("The denominator must not be negative");
226        }
227        if (numerator < 0) {
228            throw new ArithmeticException("The numerator must not be negative");
229        }
230        final long numeratorValue;
231        if (whole < 0) {
232            numeratorValue = whole * (long) denominator - numerator;
233        } else {
234            numeratorValue = whole * (long) denominator + numerator;
235        }
236        if (numeratorValue < Integer.MIN_VALUE || numeratorValue > Integer.MAX_VALUE) {
237            throw new ArithmeticException("Numerator too large to represent as an Integer.");
238        }
239        return new Fraction((int) numeratorValue, denominator);
240    }
241
242    /**
243     * Gets a Fraction from a {@link String}.
244     * <p>
245     * The formats accepted are:
246     * </p>
247     * <ol>
248     * <li>{@code double} String containing a dot</li>
249     * <li>{@code "X Y/Z"}</li>
250     * <li>{@code "Y/Z"}</li>
251     * <li>{@code "X"} (a simple whole number)</li>
252     * </ol>
253     * <p>
254     * and a {@code .}
255     * </p>
256     *
257     * @param str The string to parse, must not be {@code null}
258     * @return The new {@link Fraction} instance
259     * @throws NullPointerException  Thrown if the string is {@code null}
260     * @throws NumberFormatException Thrown if the number format is invalid, or if the string is well-formed but its value cannot be represented as a
261     *                               {@code Fraction}: a zero denominator such as {@code "1/0"}, a value outside the range of an {@code int} such as
262     *                               {@code "9999999999.5"}, or a mixed number whose combined numerator overflows. For those unrepresentable values, the causal
263     *                               {@link ArithmeticException} is preserved as the {@link Throwable#getCause() cause}.
264     */
265    public static Fraction getFraction(final String str) {
266        Objects.requireNonNull(str, "str");
267        // parse double format
268        int pos = str.indexOf('.');
269        if (pos >= 0) {
270            final double value = Double.parseDouble(str);
271            try {
272                return getFraction(value);
273            } catch (final ArithmeticException e) {
274                throw toNumberFormatException(str, e);
275            }
276        }
277
278        // parse X Y/Z format
279        pos = str.indexOf(' ');
280        if (pos > 0) {
281            final int whole = Integer.parseInt(str.substring(0, pos));
282            final String remainder = str.substring(pos + 1);
283            pos = remainder.indexOf('/');
284            if (pos < 0) {
285                throw new NumberFormatException("The fraction could not be parsed as the format X Y/Z");
286            }
287            final int numer = Integer.parseInt(remainder.substring(0, pos));
288            final int denom = Integer.parseInt(remainder.substring(pos + 1));
289            try {
290                return getFraction(whole, numer, denom);
291            } catch (final ArithmeticException e) {
292                throw toNumberFormatException(str, e);
293            }
294        }
295
296        // parse Y/Z format
297        pos = str.indexOf('/');
298        if (pos < 0) {
299            // simple whole number
300            return getFraction(Integer.parseInt(str), 1);
301        }
302        final int numer = Integer.parseInt(str.substring(0, pos));
303        final int denom = Integer.parseInt(str.substring(pos + 1));
304        try {
305            return getFraction(numer, denom);
306        } catch (final ArithmeticException e) {
307            throw toNumberFormatException(str, e);
308        }
309    }
310
311    /**
312     * Gets a reduced {@link Fraction} instance with the 2 parts of a fraction Y/Z.
313     * <p>
314     * For example, if the input parameters represent 2/4, then the created fraction will be 1/2.
315     * </p>
316     *
317     * <p>
318     * Any negative signs are resolved to be on the numerator.
319     * </p>
320     *
321     * @param numerator   The numerator, for example the three in 'three sevenths'
322     * @param denominator The denominator, for example the seven in 'three sevenths'
323     * @return A new fraction instance, with the numerator and denominator reduced
324     * @throws ArithmeticException Thrown if the denominator is {@code zero}, or the reduced numerator or positive denominator cannot be represented as an
325     *                             {@code int}.
326     */
327    public static Fraction getReducedFraction(int numerator, int denominator) {
328        checkDenominator(denominator);
329        if (numerator == 0) {
330            return ZERO; // normalize zero.
331        }
332        // Reduce common powers of two before sign normalization to avoid negating Integer.MIN_VALUE.
333        while ((numerator & 1) == 0 && (denominator & 1) == 0) {
334            numerator /= 2;
335            denominator /= 2;
336        }
337        if (denominator < 0) {
338            if (numerator == Integer.MIN_VALUE || denominator == Integer.MIN_VALUE) {
339                throw new ArithmeticException("overflow: can't negate");
340            }
341            numerator = -numerator;
342            denominator = -denominator;
343        }
344        // simplify fraction.
345        final int gcd = greatestCommonDivisor(numerator, denominator);
346        numerator /= gcd;
347        denominator /= gcd;
348        return new Fraction(numerator, denominator);
349    }
350
351    /**
352     * Gets the greatest common divisor of the absolute value of
353     * two numbers, using the "binary gcd" method which avoids
354     * division and modulo operations.  See Knuth 4.5.2 algorithm B.
355     * This algorithm is due to Josef Stein (1961).
356     *
357     * @param u  A non-zero number
358     * @param v  A non-zero number
359     * @return The greatest common divisor, never zero
360     */
361    private static int greatestCommonDivisor(int u, int v) {
362        // From Commons Math:
363        if (u == 0 || v == 0) {
364            if (u == Integer.MIN_VALUE || v == Integer.MIN_VALUE) {
365                throw new ArithmeticException("overflow: gcd is 2^31");
366            }
367            return Math.abs(u) + Math.abs(v);
368        }
369        // if either operand is abs 1, return 1:
370        if (Math.abs(u) == 1 || Math.abs(v) == 1) {
371            return 1;
372        }
373        // keep u and v negative, as negative integers range down to
374        // -2^31, while positive numbers can only be as large as 2^31-1
375        // (i.e. we can't necessarily negate a negative number without
376        // overflow)
377        if (u > 0) {
378            u = -u;
379        } // make u negative
380        if (v > 0) {
381            v = -v;
382        } // make v negative
383        // B1. [Find power of 2]
384        int k = 0;
385        while ((u & 1) == 0 && (v & 1) == 0 && k < 31) { // while u and v are both even...
386            u /= 2;
387            v /= 2;
388            k++; // cast out twos.
389        }
390        if (k == 31) {
391            throw new ArithmeticException("overflow: gcd is 2^31");
392        }
393        // B2. Initialize: u and v have been divided by 2^k and at least
394        // one is odd.
395        int t = (u & 1) == 1 ? v : -(u / 2)/* B3 */;
396        // t negative: u was odd, v may be even (t replaces v)
397        // t positive: u was even, v is odd (t replaces u)
398        do {
399            /* assert u<0 && v<0; */
400            // B4/B3: cast out twos from t.
401            while ((t & 1) == 0) { // while t is even.
402                t /= 2; // cast out twos
403            }
404            // B5 [reset max(u,v)]
405            if (t > 0) {
406                u = -t;
407            } else {
408                v = t;
409            }
410            // B6/B3. at this point both u and v should be odd.
411            t = (v - u) / 2;
412            // |u| larger: t positive (replace u)
413            // |v| larger: t negative (replace v)
414        } while (t != 0);
415        return -u * (1 << k); // gcd is u*2^k
416    }
417
418    private static int hash(final int value1, final int value2) {
419        return Objects.hash(value1, value2);
420    }
421
422    /**
423     * Multiplies two integers, checking for overflow.
424     *
425     * @param x A factor
426     * @param y A factor
427     * @return The product {@code x*y}
428     * @throws ArithmeticException Thrown if the result cannot be represented as an int.
429     */
430    private static int mulAndCheck(final int x, final int y) {
431        final long m = (long) x * (long) y;
432        if (m < Integer.MIN_VALUE || m > Integer.MAX_VALUE) {
433            throw new ArithmeticException("overflow: mul");
434        }
435        return (int) m;
436    }
437
438    /**
439     *  Multiplies two non-negative integers, checking for overflow.
440     *
441     * @param x A non-negative factor
442     * @param y A non-negative factor
443     * @return The product {@code x*y}
444     * @throws ArithmeticException Thrown if the result cannot be represented as an int.
445     */
446    private static int mulPosAndCheck(final int x, final int y) {
447        /* assert x>=0 && y>=0; */
448        final long m = (long) x * (long) y;
449        if (m > Integer.MAX_VALUE) {
450            throw new ArithmeticException("overflow: mulPos");
451        }
452        return (int) m;
453    }
454
455    /**
456     * Converts an {@link ArithmeticException} raised while parsing a string into the {@link NumberFormatException} that
457     * {@link #getFraction(String)} documents, preserving the original exception as the cause.
458     *
459     * @param str The string being parsed.
460     * @param cause The arithmetic failure: a zero denominator or a value outside the range of an {@code int}.
461     * @return The exception for the caller to throw, never {@code null}.
462     */
463    private static NumberFormatException toNumberFormatException(final String str, final ArithmeticException cause) {
464        final NumberFormatException nfe = new NumberFormatException("The fraction could not be parsed from '" + str + "': " + cause.getMessage());
465        nfe.initCause(cause);
466        return nfe;
467    }
468
469    /**
470     * The numerator number part of the fraction (the three in three sevenths).
471     */
472    private final int numerator;
473
474    /**
475     * The denominator number part of the fraction (the seven in three sevenths).
476     */
477    private final int denominator;
478
479    /**
480     * Cached output hashCode (class is immutable).
481     */
482    private final int hashCode;
483
484    /**
485     * Cached output toString (class is immutable).
486     */
487    private transient String toString;
488
489    /**
490     * Cached output toProperString (class is immutable).
491     */
492    private transient String toProperString;
493
494    /**
495     * Constructs a {@link Fraction} instance with the 2 parts
496     * of a fraction Y/Z.
497     *
498     * @param numerator  The numerator, for example the three in 'three sevenths'
499     * @param denominator  The denominator, for example the seven in 'three sevenths'
500     */
501    private Fraction(final int numerator, final int denominator) {
502        this.numerator = numerator;
503        this.denominator = denominator;
504        this.hashCode = hash(denominator, numerator);
505    }
506
507    /**
508     * Gets a fraction that is the positive equivalent of this one.
509     * <p>
510     * More precisely: {@code (fraction &gt;= 0 ? this : -fraction)}
511     * </p>
512     * <p>
513     * The returned fraction is not reduced.
514     * </p>
515     *
516     * @return {@code this} if it is positive, or a new positive fraction instance with the opposite signed numerator
517     */
518    public Fraction abs() {
519        if (numerator >= 0) {
520            return this;
521        }
522        return negate();
523    }
524
525    /**
526     * Adds the value of this fraction to another, returning the result in reduced form.
527     * The algorithm follows Knuth, 4.5.1.
528     *
529     * @param fraction  The fraction to add, must not be {@code null}
530     * @return A {@link Fraction} instance with the resulting values
531     * @throws NullPointerException Thrown if the fraction is {@code null}.
532     * @throws ArithmeticException Thrown if the resulting numerator or denominator exceeds {@code Integer.MAX_VALUE}.
533     */
534    public Fraction add(final Fraction fraction) {
535        return addSub(fraction, true /* add */);
536    }
537
538    /**
539     * Implements add and subtract using the algorithm described in <a href="https://www-cs-faculty.stanford.edu/~knuth/taocp.html">
540     * The Art of Computer Programming (TAOCP)</a> 4.5.1 by Donald Knuth.
541     *
542     * @param fraction The fraction to subtract, must not be {@code null}
543     * @param isAdd true to add, false to subtract
544     * @return A {@link Fraction} instance with the resulting values
545     * @throws IllegalArgumentException Thrown if the fraction is {@code null}.
546     * @throws ArithmeticException Thrown if the resulting numerator or denominator
547     *   cannot be represented in an {@code int}.
548     */
549    private Fraction addSub(final Fraction fraction, final boolean isAdd) {
550        Objects.requireNonNull(fraction, "fraction");
551        // zero is identity for addition.
552        if (numerator == 0) {
553            return isAdd ? fraction.reduce() : fraction.reduce().negate();
554        }
555        if (fraction.numerator == 0) {
556            return reduce();
557        }
558        // Knuth 4.5.1 assumes operands in lowest terms and this class does not reduce on
559        // construction, so reduce both first, as multiplyBy does.
560        final int thisGcd = greatestCommonDivisor(numerator, denominator);
561        final int thatGcd = greatestCommonDivisor(fraction.numerator, fraction.denominator);
562        final int thisNumerator = numerator / thisGcd;
563        final int thisDenominator = denominator / thisGcd;
564        final int thatNumerator = fraction.numerator / thatGcd;
565        final int thatDenominator = fraction.denominator / thatGcd;
566        // if denominators are randomly distributed, d1 will be 1 about 61%
567        // of the time.
568        final int d1 = greatestCommonDivisor(thisDenominator, thatDenominator);
569        if (d1 == 1) {
570            // result is ((u*v' +/- u'v) / u'v')
571            // the int cross products u*v' and u'*v can overflow even when the reduced result
572            // fits an int, so widen to long and let Math narrow the final numerator back.
573            final long uvp = (long) thisNumerator * thatDenominator;
574            final long upv = (long) thatNumerator * thisDenominator;
575            final long t = isAdd ? Math.addExact(uvp, upv) : Math.subtractExact(uvp, upv);
576            return new Fraction(Math.toIntExact(t), mulPosAndCheck(thisDenominator, thatDenominator));
577        }
578        // the quantity 't' requires 65 bits of precision; see knuth 4.5.1
579        // exercise 7. we're going to use a BigInteger.
580        // t = u(v'/d1) +/- v(u'/d1)
581        final BigInteger uvp = BigInteger.valueOf(thisNumerator).multiply(BigInteger.valueOf(thatDenominator / d1));
582        final BigInteger upv = BigInteger.valueOf(thatNumerator).multiply(BigInteger.valueOf(thisDenominator / d1));
583        final BigInteger t = isAdd ? uvp.add(upv) : uvp.subtract(upv);
584        // but d2 doesn't need extra precision because
585        // d2 = gcd(t,d1) = gcd(t mod d1, d1)
586        final int tmodd1 = t.mod(BigInteger.valueOf(d1)).intValue();
587        final int d2 = tmodd1 == 0 ? d1 : greatestCommonDivisor(tmodd1, d1);
588
589        // result is (t/d2) / (u'/d1)(v'/d2)
590        final BigInteger w = t.divide(BigInteger.valueOf(d2));
591        if (w.bitLength() > 31) {
592            throw new ArithmeticException("overflow: numerator too large after multiply");
593        }
594        return new Fraction(w.intValue(), mulPosAndCheck(thisDenominator / d1, thatDenominator / d2));
595    }
596
597    /**
598     * Compares this object to another based on size.
599     * <p>
600     * 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
601     * treats them as equal.
602     * </p>
603     *
604     * @param other The object to compare to
605     * @return -1 if this is less, 0 if equal, +1 if greater
606     * @throws ClassCastException Thrown if the object is not a {@link Fraction}.
607     * @throws NullPointerException Thrown if the object is {@code null}.
608     */
609    @Override
610    public int compareTo(final Fraction other) {
611        if (this == other || numerator == other.numerator && denominator == other.denominator) {
612            return 0;
613        }
614
615        // otherwise see which is less
616        final long first = (long) numerator * (long) other.denominator;
617        final long second = (long) other.numerator * (long) denominator;
618        return Long.compare(first, second);
619    }
620
621    /**
622     * Divide the value of this fraction by another.
623     *
624     * @param fraction  The fraction to divide by, must not be {@code null}
625     * @return A {@link Fraction} instance with the resulting values
626     * @throws NullPointerException Thrown if the fraction is {@code null}.
627     * @throws ArithmeticException Thrown if the fraction to divide by is zero.
628     * @throws ArithmeticException Thrown if the resulting numerator or denominator exceeds {@code Integer.MAX_VALUE}.
629     */
630    public Fraction divideBy(final Fraction fraction) {
631        Objects.requireNonNull(fraction, "fraction");
632        if (fraction.numerator == 0) {
633            throw new ArithmeticException("The fraction to divide by must not be zero");
634        }
635        return multiplyBy(fraction.invert());
636    }
637
638    /**
639     * Gets the fraction as a {@code double}. This calculates the fraction
640     * as the numerator divided by denominator.
641     *
642     * @return The fraction as a {@code double}
643     */
644    @Override
645    public double doubleValue() {
646        return (double) numerator / (double) denominator;
647    }
648
649    /**
650     * Compares this fraction to another object to test if they are equal.
651     * <p>
652     * To be equal, both values must be equal. Thus 2/4 is not equal to 1/2.
653     * </p>
654     *
655     * @param obj The reference object with which to compare
656     * @return {@code true} if this object is equal
657     */
658    @Override
659    public boolean equals(final Object obj) {
660        if (obj == this) {
661            return true;
662        }
663        if (!(obj instanceof Fraction)) {
664            return false;
665        }
666        final Fraction other = (Fraction) obj;
667        return getNumerator() == other.getNumerator() && getDenominator() == other.getDenominator();
668    }
669
670    /**
671     * Gets the fraction as a {@code float}. This calculates the fraction
672     * as the numerator divided by denominator.
673     *
674     * @return The fraction as a {@code float}
675     */
676    @Override
677    public float floatValue() {
678        return (float) numerator / (float) denominator;
679    }
680
681    /**
682     * Gets the denominator part of the fraction.
683     *
684     * @return The denominator fraction part
685     */
686    public int getDenominator() {
687        return denominator;
688    }
689
690    /**
691     * Gets the numerator part of the fraction.
692     * <p>
693     * This method may return a value greater than the denominator, an improper fraction, such as the seven in 7/4.
694     * </p>
695     *
696     * @return The numerator fraction part
697     */
698    public int getNumerator() {
699        return numerator;
700    }
701
702    /**
703     * Gets the proper numerator, always positive.
704     * <p>
705     * An improper fraction 7/4 can be resolved into a proper one, 1 3/4. This method returns the 3 from the proper fraction.
706     * </p>
707     *
708     * <p>
709     * 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.
710     * </p>
711     *
712     * @return The numerator fraction part of a proper fraction, always positive
713     */
714    public int getProperNumerator() {
715        return Math.abs(numerator % denominator);
716    }
717
718    /**
719     * Gets the proper whole part of the fraction.
720     * <p>
721     * An improper fraction 7/4 can be resolved into a proper one, 1 3/4. This method returns the 1 from the proper fraction.
722     * </p>
723     *
724     * <p>
725     * 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.
726     * </p>
727     *
728     * @return The whole fraction part of a proper fraction, that includes the sign
729     */
730    public int getProperWhole() {
731        return numerator / denominator;
732    }
733
734    /**
735     * Gets a hashCode for the fraction.
736     *
737     * @return A hash code value for this object
738     */
739    @Override
740    public int hashCode() {
741        return hashCode;
742    }
743
744    /**
745     * Gets the fraction as an {@code int}. This returns the whole number
746     * part of the fraction.
747     *
748     * @return The whole number fraction part
749     */
750    @Override
751    public int intValue() {
752        return numerator / denominator;
753    }
754
755    /**
756     * Gets a fraction that is the inverse (1/fraction) of this one.
757     * <p>
758     * The returned fraction is not reduced.
759     * </p>
760     *
761     * @return A new fraction instance with the numerator and denominator inverted.
762     * @throws ArithmeticException Thrown if the fraction represents zero.
763     */
764    public Fraction invert() {
765        if (numerator == 0) {
766            throw new ArithmeticException("Unable to invert zero.");
767        }
768        if (numerator == Integer.MIN_VALUE) {
769            throw new ArithmeticException("overflow: can't negate numerator");
770        }
771        if (numerator < 0) {
772            return new Fraction(-denominator, -numerator);
773        }
774        return new Fraction(denominator, numerator);
775    }
776
777    /**
778     * Gets the fraction as a {@code long}. This returns the whole number
779     * part of the fraction.
780     *
781     * @return The whole number fraction part
782     */
783    @Override
784    public long longValue() {
785        return (long) numerator / denominator;
786    }
787
788    /**
789     * Multiplies the value of this fraction by another, returning the
790     * result in reduced form.
791     *
792     * @param fraction  The fraction to multiply by, must not be {@code null}
793     * @return A {@link Fraction} instance with the resulting values
794     * @throws NullPointerException Thrown if the fraction is {@code null}.
795     * @throws ArithmeticException Thrown if the resulting numerator or denominator exceeds {@code Integer.MAX_VALUE}.
796     */
797    public Fraction multiplyBy(final Fraction fraction) {
798        Objects.requireNonNull(fraction, "fraction");
799        if (numerator == 0 || fraction.numerator == 0) {
800            return ZERO;
801        }
802        // knuth 4.5.1
803        // make sure we don't overflow unless the result *must* overflow.
804        // Reduce both operands first: the cross-gcd below cancels the cross terms only, so a
805        // factor shared inside an unreduced operand survives into the product and can overflow
806        // an int even when the reduced result fits.
807        final int thisGcd = greatestCommonDivisor(numerator, denominator);
808        final int thatGcd = greatestCommonDivisor(fraction.numerator, fraction.denominator);
809        final int thisNumerator = numerator / thisGcd;
810        final int thisDenominator = denominator / thisGcd;
811        final int thatNumerator = fraction.numerator / thatGcd;
812        final int thatDenominator = fraction.denominator / thatGcd;
813        final int d1 = greatestCommonDivisor(thisNumerator, thatDenominator);
814        final int d2 = greatestCommonDivisor(thatNumerator, thisDenominator);
815        return getReducedFraction(mulAndCheck(thisNumerator / d1, thatNumerator / d2), mulPosAndCheck(thisDenominator / d2, thatDenominator / d1));
816    }
817
818    /**
819     * Gets a fraction that is the negative (-fraction) of this one.
820     * <p>
821     * The returned fraction is not reduced.
822     * </p>
823     *
824     * @return A new fraction instance with the opposite signed numerator
825     */
826    public Fraction negate() {
827        // the positive range is one smaller than the negative range of an int.
828        if (numerator == Integer.MIN_VALUE) {
829            throw new ArithmeticException("overflow: too large to negate");
830        }
831        return new Fraction(-numerator, denominator);
832    }
833
834    /**
835     * Gets a fraction that is raised to the passed in power.
836     * <p>
837     * The returned fraction is in reduced form.
838     * </p>
839     *
840     * @param power The power to raise the fraction to
841     * @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
842     *         appropriate power
843     * @throws ArithmeticException Thrown if the resulting numerator or denominator exceeds {@code Integer.MAX_VALUE}.
844     */
845    public Fraction pow(final int power) {
846        if (power == 1) {
847            return this;
848        }
849        if (power == 0) {
850            return ONE;
851        }
852        if (power < 0) {
853            if (power == Integer.MIN_VALUE) { // MIN_VALUE can't be negated.
854                return invert().pow(2).pow(-(power / 2));
855            }
856            return invert().pow(-power);
857        }
858        final Fraction f = multiplyBy(this);
859        if (power % 2 == 0) { // if even...
860            return f.pow(power / 2);
861        }
862        return f.pow(power / 2).multiplyBy(this);
863    }
864
865    /**
866     * Validates the cached hashCode after deserialization. Throws a {@link InvalidObjectException} when the stored hashCode does not match the canonical hash
867     * of the deserialized numerator/denominator.
868     *
869     * @param in See {@link Serializable}.
870     * @throws IOException Thrown as described in {@link Serializable}.
871     * @throws ClassNotFoundException Thrown as described in {@link Serializable}.
872     * @throws InvalidObjectException Thrown if the hashCode doesn't match the denominator and numerator.
873     */
874    private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
875        in.defaultReadObject();
876        checkDenominator(denominator);
877        if (hashCode != hash(denominator, numerator)) {
878            throw new InvalidObjectException("Fraction hashCode does not match numerator/denominator.");
879        }
880    }
881
882    /**
883     * Reduce the fraction to the smallest values for the numerator and denominator, returning the result.
884     * <p>
885     * For example, if this fraction represents 2/4, then the result will be 1/2.
886     * </p>
887     *
888     * @return A new reduced fraction instance, or this if no simplification possible
889     */
890    public Fraction reduce() {
891        if (numerator == 0) {
892            return equals(ZERO) ? this : ZERO;
893        }
894        final int gcd = greatestCommonDivisor(Math.abs(numerator), denominator);
895        if (gcd == 1) {
896            return this;
897        }
898        return getFraction(numerator / gcd, denominator / gcd);
899    }
900
901    /**
902     * Subtracts the value of another fraction from the value of this one,
903     * returning the result in reduced form.
904     *
905     * @param fraction  The fraction to subtract, must not be {@code null}
906     * @return A {@link Fraction} instance with the resulting values
907     * @throws NullPointerException Thrown if the fraction is {@code null}.
908     * @throws ArithmeticException Thrown if the resulting numerator or denominator
909     *   cannot be represented in an {@code int}.
910     */
911    public Fraction subtract(final Fraction fraction) {
912        return addSub(fraction, false /* subtract */);
913    }
914
915    /**
916     * Gets the fraction as a proper {@link String} in the format X Y/Z.
917     * <p>
918     * 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
919     * zero, only the whole number is returned.
920     * </p>
921     *
922     * @return A {@link String} form of the fraction
923     */
924    public String toProperString() {
925        if (toProperString == null) {
926            if (numerator == 0) {
927                toProperString = "0";
928            } else if (numerator == denominator) {
929                toProperString = "1";
930            } else if (numerator == -1 * denominator) {
931                toProperString = "-1";
932            } else if ((numerator > 0 ? -numerator : numerator) < -denominator) {
933                // note that we do the magnitude comparison test above with
934                // NEGATIVE (not positive) numbers, since negative numbers
935                // have a larger range. otherwise numerator == Integer.MIN_VALUE
936                // is handled incorrectly.
937                final int properNumerator = getProperNumerator();
938                if (properNumerator == 0) {
939                    toProperString = Integer.toString(getProperWhole());
940                } else {
941                    toProperString = getProperWhole() + " " + properNumerator + "/" + getDenominator();
942                }
943            } else {
944                toProperString = getNumerator() + "/" + getDenominator();
945            }
946        }
947        return toProperString;
948    }
949
950    /**
951     * Gets the fraction as a {@link String}.
952     * <p>
953     * The format used is '<em>numerator</em>/<em>denominator</em>' always.
954     * </p>
955     *
956     * @return A {@link String} form of the fraction
957     */
958    @Override
959    public String toString() {
960        if (toString == null) {
961            toString = getNumerator() + "/" + getDenominator();
962        }
963        return toString;
964    }
965}