    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.Serializable;
    020import java.math.BigInteger;
    021import java.util.Objects;
    022
    023/**
    024 * {@link Fraction} is a {@link Number} implementation that stores fractions accurately.
    025 * <p>
    026 * This class is immutable, and interoperable with most methods that accept a {@link Number}.
    027 * </p>
    028 * <p>
    029 * 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
    030 * equivalent, please see the Commons Math BigFraction class.
    031 * </p>
    032 *
    033 * @since 2.0
    034 */
    035public final class Fraction extends Number implements Comparable<Fraction> {
    036
    037    /**
    038     * Required for serialization support. Lang version 2.0.
    039     *
    040     * @see Serializable
    041     */
    042    private static final long serialVersionUID = 65382027393090L;
    043
    044    /**
    045     * {@link Fraction} representation of 0.
    046     */
    047    public static final Fraction ZERO = new Fraction(0, 1);
    048
    049    /**
    050     * {@link Fraction} representation of 1.
    051     */
    052    public static final Fraction ONE = new Fraction(1, 1);
    053
    054    /**
    055     * {@link Fraction} representation of 1/2.
    056     */
    057    public static final Fraction ONE_HALF = new Fraction(1, 2);
    058
    059    /**
    060     * {@link Fraction} representation of 1/3.
    061     */
    062    public static final Fraction ONE_THIRD = new Fraction(1, 3);
    063
    064    /**
    065     * {@link Fraction} representation of 2/3.
    066     */
    067    public static final Fraction TWO_THIRDS = new Fraction(2, 3);
    068
    069    /**
    070     * {@link Fraction} representation of 1/4.
    071     */
    072    public static final Fraction ONE_QUARTER = new Fraction(1, 4);
    073
    074    /**
    075     * {@link Fraction} representation of 2/4.
    076     */
    077    public static final Fraction TWO_QUARTERS = new Fraction(2, 4);
    078
    079    /**
    080     * {@link Fraction} representation of 3/4.
    081     */
    082    public static final Fraction THREE_QUARTERS = new Fraction(3, 4);
    083
    084    /**
    085     * {@link Fraction} representation of 1/5.
    086     */
    087    public static final Fraction ONE_FIFTH = new Fraction(1, 5);
    088
    089    /**
    090     * {@link Fraction} representation of 2/5.
    091     */
    092    public static final Fraction TWO_FIFTHS = new Fraction(2, 5);
    093
    094    /**
    095     * {@link Fraction} representation of 3/5.
    096     */
    097    public static final Fraction THREE_FIFTHS = new Fraction(3, 5);
    098
    099    /**
    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 transient 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    }
    493
    494    /**
    495     * Gets a fraction that is the positive equivalent of this one.
    496     * <p>
    497     * More precisely: {@code (fraction &gt;= 0 ? this : -fraction)}
    498     * </p>
    499     * <p>
    500     * The returned fraction is not reduced.
    501     * </p>
    502     *
    503     * @return {@code this} if it is positive, or a new positive fraction instance with the opposite signed numerator
    504     */
    505    public Fraction abs() {
    506        if (numerator >= 0) {
    507            return this;
    508        }
    509        return negate();
    510    }
    511
    512    /**
    513     * Adds the value of this fraction to another, returning the result in reduced form.
    514     * The algorithm follows Knuth, 4.5.1.
    515     *
    516     * @param fraction  the fraction to add, must not be {@code null}
    517     * @return a {@link Fraction} instance with the resulting values
    518     * @throws NullPointerException if the fraction is {@code null}
    519     * @throws ArithmeticException if the resulting numerator or denominator exceeds
    520     *  {@code Integer.MAX_VALUE}
    521     */
    522    public Fraction add(final Fraction fraction) {
    523        return addSub(fraction, true /* add */);
    524    }
    525
    526    /**
    527     * Implements add and subtract using the algorithm described in <a href="https://www-cs-faculty.stanford.edu/~knuth/taocp.html">
    528     * The Art of Computer Programming (TAOCP)</a> 4.5.1 by Donald Knuth.
    529     *
    530     * @param fraction the fraction to subtract, must not be {@code null}
    531     * @param isAdd true to add, false to subtract
    532     * @return a {@link Fraction} instance with the resulting values
    533     * @throws IllegalArgumentException if the fraction is {@code null}
    534     * @throws ArithmeticException if the resulting numerator or denominator
    535     *   cannot be represented in an {@code int}.
    536     */
    537    private Fraction addSub(final Fraction fraction, final boolean isAdd) {
    538        Objects.requireNonNull(fraction, "fraction");
    539        // zero is identity for addition.
    540        if (numerator == 0) {
    541            return isAdd ? fraction : fraction.negate();
    542        }
    543        if (fraction.numerator == 0) {
    544            return this;
    545        }
    546        // if denominators are randomly distributed, d1 will be 1 about 61%
    547        // of the time.
    548        final int d1 = greatestCommonDivisor(denominator, fraction.denominator);
    549        if (d1 == 1) {
    550            // result is ((u*v' +/- u'v) / u'v')
    551            final int uvp = mulAndCheck(numerator, fraction.denominator);
    552            final int upv = mulAndCheck(fraction.numerator, denominator);
    553            return new Fraction(isAdd ? addAndCheck(uvp, upv) : subAndCheck(uvp, upv), mulPosAndCheck(denominator,
    554                    fraction.denominator));
    555        }
    556        // the quantity 't' requires 65 bits of precision; see knuth 4.5.1
    557        // exercise 7. we're going to use a BigInteger.
    558        // t = u(v'/d1) +/- v(u'/d1)
    559        final BigInteger uvp = BigInteger.valueOf(numerator).multiply(BigInteger.valueOf(fraction.denominator / d1));
    560        final BigInteger upv = BigInteger.valueOf(fraction.numerator).multiply(BigInteger.valueOf(denominator / d1));
    561        final BigInteger t = isAdd ? uvp.add(upv) : uvp.subtract(upv);
    562        // but d2 doesn't need extra precision because
    563        // d2 = gcd(t,d1) = gcd(t mod d1, d1)
    564        final int tmodd1 = t.mod(BigInteger.valueOf(d1)).intValue();
    565        final int d2 = tmodd1 == 0 ? d1 : greatestCommonDivisor(tmodd1, d1);
    566
    567        // result is (t/d2) / (u'/d1)(v'/d2)
    568        final BigInteger w = t.divide(BigInteger.valueOf(d2));
    569        if (w.bitLength() > 31) {
    570            throw new ArithmeticException("overflow: numerator too large after multiply");
    571        }
    572        return new Fraction(w.intValue(), mulPosAndCheck(denominator / d1, fraction.denominator / d2));
    573    }
    574
    575    /**
    576     * Compares this object to another based on size.
    577     * <p>
    578     * 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
    579     * treats them as equal.
    580     * </p>
    581     *
    582     * @param other the object to compare to
    583     * @return -1 if this is less, 0 if equal, +1 if greater
    584     * @throws ClassCastException   if the object is not a {@link Fraction}
    585     * @throws NullPointerException if the object is {@code null}
    586     */
    587    @Override
    588    public int compareTo(final Fraction other) {
    589        if (this == other) {
    590            return 0;
    591        }
    592        if (numerator == other.numerator && denominator == other.denominator) {
    593            return 0;
    594        }
    595
    596        // otherwise see which is less
    597        final long first = (long) numerator * (long) other.denominator;
    598        final long second = (long) other.numerator * (long) denominator;
    599        return Long.compare(first, second);
    600    }
    601
    602    /**
    603     * Divide the value of this fraction by another.
    604     *
    605     * @param fraction  the fraction to divide by, must not be {@code null}
    606     * @return a {@link Fraction} instance with the resulting values
    607     * @throws NullPointerException if the fraction is {@code null}
    608     * @throws ArithmeticException if the fraction to divide by is zero
    609     * @throws ArithmeticException if the resulting numerator or denominator exceeds
    610     *  {@code Integer.MAX_VALUE}
    611     */
    612    public Fraction divideBy(final Fraction fraction) {
    613        Objects.requireNonNull(fraction, "fraction");
    614        if (fraction.numerator == 0) {
    615            throw new ArithmeticException("The fraction to divide by must not be zero");
    616        }
    617        return multiplyBy(fraction.invert());
    618    }
    619
    620    /**
    621     * Gets the fraction as a {@code double}. This calculates the fraction
    622     * as the numerator divided by denominator.
    623     *
    624     * @return the fraction as a {@code double}
    625     */
    626    @Override
    627    public double doubleValue() {
    628        return (double) numerator / (double) denominator;
    629    }
    630
    631    /**
    632     * Compares this fraction to another object to test if they are equal.
    633     * <p>
    634     * To be equal, both values must be equal. Thus 2/4 is not equal to 1/2.
    635     * </p>
    636     *
    637     * @param obj the reference object with which to compare
    638     * @return {@code true} if this object is equal
    639     */
    640    @Override
    641    public boolean equals(final Object obj) {
    642        if (obj == this) {
    643            return true;
    644        }
    645        if (!(obj instanceof Fraction)) {
    646            return false;
    647        }
    648        final Fraction other = (Fraction) obj;
    649        return getNumerator() == other.getNumerator() && getDenominator() == other.getDenominator();
    650    }
    651
    652    /**
    653     * Gets the fraction as a {@code float}. This calculates the fraction
    654     * as the numerator divided by denominator.
    655     *
    656     * @return the fraction as a {@code float}
    657     */
    658    @Override
    659    public float floatValue() {
    660        return (float) numerator / (float) denominator;
    661    }
    662
    663    /**
    664     * Gets the denominator part of the fraction.
    665     *
    666     * @return the denominator fraction part
    667     */
    668    public int getDenominator() {
    669        return denominator;
    670    }
    671
    672    /**
    673     * Gets the numerator part of the fraction.
    674     * <p>
    675     * This method may return a value greater than the denominator, an improper fraction, such as the seven in 7/4.
    676     * </p>
    677     *
    678     * @return the numerator fraction part
    679     */
    680    public int getNumerator() {
    681        return numerator;
    682    }
    683
    684    /**
    685     * Gets the proper numerator, always positive.
    686     * <p>
    687     * An improper fraction 7/4 can be resolved into a proper one, 1 3/4. This method returns the 3 from the proper fraction.
    688     * </p>
    689     *
    690     * <p>
    691     * 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.
    692     * </p>
    693     *
    694     * @return the numerator fraction part of a proper fraction, always positive
    695     */
    696    public int getProperNumerator() {
    697        return Math.abs(numerator % denominator);
    698    }
    699
    700    /**
    701     * Gets the proper whole part of the fraction.
    702     * <p>
    703     * An improper fraction 7/4 can be resolved into a proper one, 1 3/4. This method returns the 1 from the proper fraction.
    704     * </p>
    705     *
    706     * <p>
    707     * 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.
    708     * </p>
    709     *
    710     * @return the whole fraction part of a proper fraction, that includes the sign
    711     */
    712    public int getProperWhole() {
    713        return numerator / denominator;
    714    }
    715
    716    /**
    717     * Gets a hashCode for the fraction.
    718     *
    719     * @return a hash code value for this object
    720     */
    721    @Override
    722    public int hashCode() {
    723        if (hashCode == 0) {
    724            // hash code update should be atomic.
    725            hashCode = Objects.hash(denominator, numerator);
    726        }
    727        return hashCode;
    728    }
    729
    730    /**
    731     * Gets the fraction as an {@code int}. This returns the whole number
    732     * part of the fraction.
    733     *
    734     * @return the whole number fraction part
    735     */
    736    @Override
    737    public int intValue() {
    738        return numerator / denominator;
    739    }
    740
    741    /**
    742     * Gets a fraction that is the inverse (1/fraction) of this one.
    743     * <p>
    744     * The returned fraction is not reduced.
    745     * </p>
    746     *
    747     * @return a new fraction instance with the numerator and denominator inverted.
    748     * @throws ArithmeticException if the fraction represents zero.
    749     */
    750    public Fraction invert() {
    751        if (numerator == 0) {
    752            throw new ArithmeticException("Unable to invert zero.");
    753        }
    754        if (numerator == Integer.MIN_VALUE) {
    755            throw new ArithmeticException("overflow: can't negate numerator");
    756        }
    757        if (numerator < 0) {
    758            return new Fraction(-denominator, -numerator);
    759        }
    760        return new Fraction(denominator, numerator);
    761    }
    762
    763    /**
    764     * Gets the fraction as a {@code long}. This returns the whole number
    765     * part of the fraction.
    766     *
    767     * @return the whole number fraction part
    768     */
    769    @Override
    770    public long longValue() {
    771        return (long) numerator / denominator;
    772    }
    773
    774    /**
    775     * Multiplies the value of this fraction by another, returning the
    776     * result in reduced form.
    777     *
    778     * @param fraction  the fraction to multiply by, must not be {@code null}
    779     * @return a {@link Fraction} instance with the resulting values
    780     * @throws NullPointerException if the fraction is {@code null}
    781     * @throws ArithmeticException if the resulting numerator or denominator exceeds
    782     *  {@code Integer.MAX_VALUE}
    783     */
    784    public Fraction multiplyBy(final Fraction fraction) {
    785        Objects.requireNonNull(fraction, "fraction");
    786        if (numerator == 0 || fraction.numerator == 0) {
    787            return ZERO;
    788        }
    789        // knuth 4.5.1
    790        // make sure we don't overflow unless the result *must* overflow.
    791        final int d1 = greatestCommonDivisor(numerator, fraction.denominator);
    792        final int d2 = greatestCommonDivisor(fraction.numerator, denominator);
    793        return getReducedFraction(mulAndCheck(numerator / d1, fraction.numerator / d2), mulPosAndCheck(denominator / d2, fraction.denominator / d1));
    794    }
    795
    796    /**
    797     * Gets a fraction that is the negative (-fraction) of this one.
    798     * <p>
    799     * The returned fraction is not reduced.
    800     * </p>
    801     *
    802     * @return a new fraction instance with the opposite signed numerator
    803     */
    804    public Fraction negate() {
    805        // the positive range is one smaller than the negative range of an int.
    806        if (numerator == Integer.MIN_VALUE) {
    807            throw new ArithmeticException("overflow: too large to negate");
    808        }
    809        return new Fraction(-numerator, denominator);
    810    }
    811
    812    /**
    813     * Gets a fraction that is raised to the passed in power.
    814     * <p>
    815     * The returned fraction is in reduced form.
    816     * </p>
    817     *
    818     * @param power the power to raise the fraction to
    819     * @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
    820     *         appropriate power
    821     * @throws ArithmeticException if the resulting numerator or denominator exceeds {@code Integer.MAX_VALUE}
    822     */
    823    public Fraction pow(final int power) {
    824        if (power == 1) {
    825            return this;
    826        }
    827        if (power == 0) {
    828            return ONE;
    829        }
    830        if (power < 0) {
    831            if (power == Integer.MIN_VALUE) { // MIN_VALUE can't be negated.
    832                return invert().pow(2).pow(-(power / 2));
    833            }
    834            return invert().pow(-power);
    835        }
    836        final Fraction f = multiplyBy(this);
    837        if (power % 2 == 0) { // if even...
    838            return f.pow(power / 2);
    839        }
    840        return f.pow(power / 2).multiplyBy(this);
    841    }
    842
    843    /**
    844     * Reduce the fraction to the smallest values for the numerator and denominator, returning the result.
    845     * <p>
    846     * For example, if this fraction represents 2/4, then the result will be 1/2.
    847     * </p>
    848     *
    849     * @return a new reduced fraction instance, or this if no simplification possible
    850     */
    851    public Fraction reduce() {
    852        if (numerator == 0) {
    853            return equals(ZERO) ? this : ZERO;
    854        }
    855        final int gcd = greatestCommonDivisor(Math.abs(numerator), denominator);
    856        if (gcd == 1) {
    857            return this;
    858        }
    859        return getFraction(numerator / gcd, denominator / gcd);
    860    }
    861
    862    /**
    863     * Subtracts the value of another fraction from the value of this one,
    864     * returning the result in reduced form.
    865     *
    866     * @param fraction  the fraction to subtract, must not be {@code null}
    867     * @return a {@link Fraction} instance with the resulting values
    868     * @throws NullPointerException if the fraction is {@code null}
    869     * @throws ArithmeticException if the resulting numerator or denominator
    870     *   cannot be represented in an {@code int}.
    871     */
    872    public Fraction subtract(final Fraction fraction) {
    873        return addSub(fraction, false /* subtract */);
    874    }
    875
    876    /**
    877     * Gets the fraction as a proper {@link String} in the format X Y/Z.
    878     * <p>
    879     * 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
    880     * zero, only the whole number is returned.
    881     * </p>
    882     *
    883     * @return a {@link String} form of the fraction
    884     */
    885    public String toProperString() {
    886        if (toProperString == null) {
    887            if (numerator == 0) {
    888                toProperString = "0";
    889            } else if (numerator == denominator) {
    890                toProperString = "1";
    891            } else if (numerator == -1 * denominator) {
    892                toProperString = "-1";
    893            } else if ((numerator > 0 ? -numerator : numerator) < -denominator) {
    894                // note that we do the magnitude comparison test above with
    895                // NEGATIVE (not positive) numbers, since negative numbers
    896                // have a larger range. otherwise numerator == Integer.MIN_VALUE
    897                // is handled incorrectly.
    898                final int properNumerator = getProperNumerator();
    899                if (properNumerator == 0) {
    900                    toProperString = Integer.toString(getProperWhole());
    901                } else {
    902                    toProperString = getProperWhole() + " " + properNumerator + "/" + getDenominator();
    903                }
    904            } else {
    905                toProperString = getNumerator() + "/" + getDenominator();
    906            }
    907        }
    908        return toProperString;
    909    }
    910
    911    /**
    912     * Gets the fraction as a {@link String}.
    913     * <p>
    914     * The format used is '<em>numerator</em>/<em>denominator</em>' always.
    915     * </p>
    916     *
    917     * @return a {@link String} form of the fraction
    918     */
    919    @Override
    920    public String toString() {
    921        if (toString == null) {
    922            toString = getNumerator() + "/" + getDenominator();
    923        }
    924        return toString;
    925    }
    926}