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 *      http://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.numbers.fraction;
018
019import java.io.Serializable;
020import org.apache.commons.numbers.core.ArithmeticUtils;
021import org.apache.commons.numbers.core.NativeOperators;
022
023/**
024 * Representation of a rational number.
025 */
026public final class Fraction
027    extends Number
028    implements Comparable<Fraction>,
029               NativeOperators<Fraction>,
030               Serializable {
031    /** A fraction representing "1". */
032    public static final Fraction ONE = new Fraction(1, 1);
033    /** A fraction representing "0". */
034    public static final Fraction ZERO = new Fraction(0, 1);
035    /** Serializable version identifier. */
036    private static final long serialVersionUID = 20190701L;
037    /** The default epsilon used for convergence. */
038    private static final double DEFAULT_EPSILON = 1e-5;
039    /** The denominator of this fraction reduced to lowest terms. */
040    private final int denominator;
041    /** The numerator of this fraction reduced to lowest terms. */
042    private final int numerator;
043
044    /**
045     * Create a fraction given the double value and either the maximum error
046     * allowed or the maximum number of denominator digits.
047     * <p>
048     *
049     * NOTE: This constructor is called with EITHER
050     *   - a valid epsilon value and the maxDenominator set to Integer.MAX_VALUE
051     *     (that way the maxDenominator has no effect).
052     * OR
053     *   - a valid maxDenominator value and the epsilon value set to zero
054     *     (that way epsilon only has effect if there is an exact match before
055     *     the maxDenominator value is reached).
056     * </p><p>
057     *
058     * It has been done this way so that the same code can be (re)used for both
059     * scenarios. However this could be confusing to users if it were part of
060     * the public API and this constructor should therefore remain PRIVATE.
061     * </p>
062     *
063     * See JIRA issue ticket MATH-181 for more details:
064     *     https://issues.apache.org/jira/browse/MATH-181
065     *
066     * @param value the double value to convert to a fraction.
067     * @param epsilon maximum error allowed.  The resulting fraction is
068     * within {@code epsilon} of {@code value}, in absolute terms.
069     * @param maxDenominator maximum denominator value allowed.
070     * @param maxIterations maximum number of convergents
071     * @throws ArithmeticException if the continued fraction failed
072     * to converge.
073     */
074    private Fraction(double value, double epsilon, int maxDenominator, int maxIterations) {
075        final long overflow = Integer.MAX_VALUE;
076        double r0 = value;
077        long a0 = (long)Math.floor(r0);
078        if (Math.abs(a0) > overflow) {
079            throw new FractionException(FractionException.ERROR_CONVERSION, value, a0, 1L);
080        }
081
082        // check for (almost) integer arguments, which should not go to iterations.
083        if (Math.abs(a0 - value) < epsilon) {
084            this.numerator = (int) a0;
085            this.denominator = 1;
086            return;
087        }
088
089        long p0 = 1;
090        long q0 = 0;
091        long p1 = a0;
092        long q1 = 1;
093
094        long p2 = 0;
095        long q2 = 1;
096
097        int n = 0;
098        boolean stop = false;
099        do {
100            ++n;
101            final double r1 = 1.0 / (r0 - a0);
102            final long a1 = (long)Math.floor(r1);
103            p2 = (a1 * p1) + p0;
104            q2 = (a1 * q1) + q0;
105
106            if (Math.abs(p2) > overflow ||
107                Math.abs(q2) > overflow) {
108                // in maxDenominator mode, if the last fraction was very close to the actual value
109                // q2 may overflow in the next iteration; in this case return the last one.
110                if (epsilon == 0.0 &&
111                    Math.abs(q1) < maxDenominator) {
112                    break;
113                }
114                throw new FractionException(FractionException.ERROR_CONVERSION, value, p2, q2);
115            }
116
117            final double convergent = (double)p2 / (double)q2;
118            if (n < maxIterations &&
119                Math.abs(convergent - value) > epsilon &&
120                q2 < maxDenominator) {
121                p0 = p1;
122                p1 = p2;
123                q0 = q1;
124                q1 = q2;
125                a0 = a1;
126                r0 = r1;
127            } else {
128                stop = true;
129            }
130        } while (!stop);
131
132        if (n >= maxIterations) {
133            throw new FractionException(FractionException.ERROR_CONVERSION, value, maxIterations);
134        }
135
136        if (q2 < maxDenominator) {
137            this.numerator = (int) p2;
138            this.denominator = (int) q2;
139        } else {
140            this.numerator = (int) p1;
141            this.denominator = (int) q1;
142        }
143    }
144
145    /**
146     * Constructs an instance.
147     *
148     * @param num Numerator.
149     * @param den Nenominator.
150     * @throws ArithmeticException if the denominator is {@code zero}
151     * or if integer overflow occurs.
152     */
153    private Fraction(int num, int den) {
154        if (den == 0) {
155            throw new ArithmeticException("division by zero");
156        }
157
158        if (num == den) {
159            numerator = 1;
160            denominator = 1;
161        } else {
162            // If num and den are both 2^-31, or if one is 0 and the other is 2^-31,
163            // the calculation of the gcd below will fail. Ensure that this does not
164            // happen by dividing both by 2 in case both are even.
165            if (((num | den) & 1) == 0) {
166                num >>= 1;
167                den >>= 1;
168            }
169
170            // Reduce numerator and denominator by greatest common divisor.
171            final int d = ArithmeticUtils.gcd(num, den);
172            if (d > 1) {
173                num /= d;
174                den /= d;
175            }
176
177            numerator = num;
178            denominator = den;
179        }
180    }
181
182    /**
183     * Creates an instance.
184     *
185     * @param value Value to convert to a fraction.
186     * @throws ArithmeticException if the continued fraction failed to
187     * converge.
188     * @return a new instance.
189     */
190    public static Fraction from(double value) {
191        return from(value, DEFAULT_EPSILON, 100);
192    }
193
194    /**
195     * Create a fraction given the double value and maximum error allowed.
196     *
197     * <p>
198     * References:
199     * <ul>
200     * <li><a href="http://mathworld.wolfram.com/ContinuedFraction.html">
201     * Continued Fraction</a> equations (11) and (22)-(26)</li>
202     * </ul>
203     *
204     * @param value the double value to convert to a fraction.
205     * @param epsilon maximum error allowed.  The resulting fraction is within
206     * {@code epsilon} of {@code value}, in absolute terms.
207     * @param maxIterations maximum number of convergents
208     * @throws ArithmeticException if the continued fraction failed to
209     * converge.
210     * @return a new instance.
211     */
212    public static Fraction from(double value, double epsilon, int maxIterations) {
213        return new Fraction(value, epsilon, Integer.MAX_VALUE, maxIterations);
214    }
215
216    /**
217     * Creates an instance.
218     *
219     * <p>
220     * References:
221     * <ul>
222     * <li><a href="http://mathworld.wolfram.com/ContinuedFraction.html">
223     * Continued Fraction</a> equations (11) and (22)-(26)</li>
224     * </ul>
225     *
226     * @param value the double value to convert to a fraction.
227     * @param maxDenominator The maximum allowed value for denominator
228     * @throws ArithmeticException if the continued fraction failed to
229     * converge.
230     * @return a new instance.
231     */
232    public static Fraction from(double value, int maxDenominator) {
233        return new Fraction(value, 0, maxDenominator, 100);
234    }
235
236    /**
237     * Creates an instance.
238     * The fraction is {@code num / 1}.
239     *
240     * @param num Numerator.
241     * @return a new instance.
242     */
243    public static Fraction of(int num) {
244        return of(num, 1);
245    }
246
247    /**
248     * Return a fraction given the numerator and denominator.
249     * The fraction is reduced to lowest terms.
250     *
251     * @param num Numerator.
252     * @param den Denominator.
253     * @throws ArithmeticException if the denominator is {@code zero}
254     * or if integer overflow occurs.
255     * @return a new instance.
256     */
257    public static Fraction of(int num, int den) {
258        return new Fraction(num, den);
259    }
260
261    /**
262     * Returns the absolute value of this fraction.
263     *
264     * @return the absolute value.
265     */
266    public Fraction abs() {
267        return signum() >= 0 ?
268            this :
269            negate();
270    }
271
272    /**
273     * Compares this object to another based on size.
274     *
275     * @param other Object to compare to.
276     * @return -1 if this is less than {@code object}, +1 if this is greater
277     * than {@code object}, 0 if they are equal.
278     */
279    @Override
280    public int compareTo(Fraction other) {
281        return Long.compare(((long) numerator) * other.denominator,
282                            ((long) denominator) * other.numerator);
283    }
284
285    /**
286     * Retrieves the {@code double} value closest to this fraction.
287     * This calculates the fraction as numerator divided by denominator.
288     *
289     * @return the fraction as a {@code double}.
290     */
291    @Override
292    public double doubleValue() {
293        return (double) numerator / (double) denominator;
294    }
295
296    /**
297     * Test for the equality of two fractions.
298     * If the lowest term numerator and denominators are the same for
299     * both fractions, the two fractions are considered to be equal.
300     * @param other Fraction to test for equality with.
301     * @return {@code true} if the two fractions are equal, {@code false}
302     * otherwise.
303     */
304    @Override
305    public boolean equals(Object other) {
306        if (this == other) {
307            return true;
308        }
309
310        if (other instanceof Fraction) {
311            // Since fractions are always in lowest terms, numerators and
312            // denominators can be compared directly for equality.
313            final Fraction rhs = (Fraction) other;
314            if (signum() == rhs.signum()) {
315                return Math.abs(numerator) == Math.abs(rhs.numerator) &&
316                    Math.abs(denominator) == Math.abs(rhs.denominator);
317            } else {
318                return false;
319            }
320        }
321
322        return false;
323    }
324
325    /**
326     * Retrieves the {@code float} value closest to this fraction.
327     * This calculates the fraction as numerator divided by denominator.
328     *
329     * @return the fraction as {@code float}.
330     */
331    @Override
332    public float floatValue() {
333        return (float) doubleValue();
334    }
335
336    /**
337     * @return the denominator.
338     */
339    public int getDenominator() {
340        return denominator;
341    }
342
343    /**
344     * @return the numerator.
345     */
346    public int getNumerator() {
347        return numerator;
348    }
349
350    /** {@inheritDoc} */
351    @Override
352    public int hashCode() {
353        return 37 * (37 * 17 + numerator) + denominator;
354    }
355
356    /**
357     * Retrieves the whole number part of the fraction.
358     *
359     * @return the largest {@code int} value that is not larger than
360     * this fraction.
361     */
362    @Override
363    public int intValue() {
364        return (int) doubleValue();
365    }
366
367    /**
368     * Retrieves the whole number part of the fraction.
369     *
370     * @return the largest {@code long} value that is not larger than
371     * this fraction.
372     */
373    @Override
374    public long longValue() {
375        return (long) doubleValue();
376    }
377
378    /**
379     * Retrieves the sign of this fraction.
380     *
381     * @return -1 if the value is strictly negative, 1 if it is strictly
382     * positive, 0 if it is 0.
383     */
384    public int signum() {
385        if ((numerator > 0 && denominator > 0) ||
386            (numerator < 0 && denominator < 0)) {
387            return 1;
388        } else if (numerator == 0) {
389            return 0;
390        } else {
391            return -1;
392        }
393    }
394
395    /**
396     * Computes the additive inverse of this fraction.
397     *
398     * @return the opposite.
399     */
400    @Override
401    public Fraction negate() {
402        return numerator == Integer.MIN_VALUE ?
403            new Fraction(numerator, -denominator) :
404            new Fraction(-numerator, denominator);
405    }
406
407    /**
408     * Computes the multiplicative inverse of this fraction.
409     *
410     * @return the reciprocal.
411     */
412    @Override
413    public Fraction reciprocal() {
414        return new Fraction(denominator, numerator);
415    }
416
417    /**
418     * Adds the value of this fraction to another, returning the result
419     * in reduced form.
420     * The algorithm follows Knuth, 4.5.1.
421     *
422     * @param fraction Fraction to add.
423     * @return a new instance.
424     * @throws ArithmeticException if the resulting numerator or denominator
425     * cannot be represented in an {@code int}.
426     */
427    @Override
428    public Fraction add(Fraction fraction) {
429        return addSub(fraction, true /* add */);
430    }
431
432    /**
433     * Adds an integer to the fraction.
434     *
435     * @param i Value to add.
436     * @return {@code this + i}.
437     */
438    public Fraction add(final int i) {
439        return new Fraction(numerator + i * denominator, denominator);
440    }
441
442    /**
443     * Subtracts the value of another fraction from the value of this one,
444     * returning the result in reduced form.
445     *
446     * @param fraction Fraction to subtract.
447     * @return a new instance.
448     * @throws ArithmeticException if the resulting numerator or denominator
449     * cannot be represented in an {@code int}.
450     */
451    @Override
452    public Fraction subtract(Fraction fraction) {
453        return addSub(fraction, false /* subtract */);
454    }
455
456    /**
457     * Subtracts an integer from this fraction.
458     *
459     * @param i Value to subtract.
460     * @return {@code this - i}.
461     */
462    public Fraction subtract(final int i) {
463        return new Fraction(numerator - i * denominator, denominator);
464    }
465
466    /**
467     * Implements add and subtract using algorithm described in Knuth 4.5.1.
468     *
469     * @param fraction Fraction to add or subtract.
470     * @param isAdd Whether the operation is "add" or "subtract".
471     * @return a new instance.
472     * @throws ArithmeticException if the resulting numerator or denominator
473     * cannot be represented in an {@code int}.
474     */
475    private Fraction addSub(Fraction fraction, boolean isAdd) {
476        // Zero is identity for addition.
477        if (numerator == 0) {
478            return isAdd ? fraction : fraction.negate();
479        }
480
481        if (fraction.numerator == 0) {
482            return this;
483        }
484
485        /*
486         * Let the two fractions be u/u' and v/v', and d1 = gcd(u', v').
487         * First, compute t, defined as:
488         *
489         * t = u(v'/d1) +/- v(u'/d1)
490         */
491        final int d1 = ArithmeticUtils.gcd(denominator, fraction.denominator);
492        final long uvp = (long) numerator * (long) (fraction.denominator / d1);
493        final long upv = (long) fraction.numerator * (long) (denominator / d1);
494
495        /*
496         * The largest possible absolute value of a product of two ints is 2^62,
497         * which can only happen as a result of -2^31 * -2^31 = 2^62, so a
498         * product of -2^62 is not possible. It follows that (uvp - upv) cannot
499         * overflow, and (uvp + upv) could only overflow if uvp = upv = 2^62.
500         * But for this to happen, the terms u, v, v'/d1 and u'/d1 would all
501         * have to be -2^31, which is not possible because v'/d1 and u'/d1
502         * are necessarily coprime.
503         */
504        final long t = isAdd ? uvp + upv : uvp - upv;
505
506        /*
507         * Because u is coprime to u' and v is coprime to v', t is necessarily
508         * coprime to both v'/d1 and u'/d1. However, it might have a common
509         * factor with d1.
510         */
511        final long d2 = ArithmeticUtils.gcd(t, d1);
512        // result is (t/d2) / (u'/d1)(v'/d2)
513        return of(Math.toIntExact(t / d2),
514                  Math.multiplyExact(denominator / d1,
515                                     fraction.denominator / (int) d2));
516    }
517
518    /**
519     * Multiplies the value of this fraction by another, returning the
520     * result in reduced form.
521     *
522     * @param fraction Fraction to multiply by.
523     * @return a new instance.
524     * @throws ArithmeticException if the resulting numerator or denominator
525     * cannot be represented in an {@code int}.
526     */
527    @Override
528    public Fraction multiply(Fraction fraction) {
529        if (numerator == 0 ||
530            fraction.numerator == 0) {
531            return ZERO;
532        }
533
534        // knuth 4.5.1
535        // Make sure we don't overflow unless the result *must* overflow.
536        final int d1 = ArithmeticUtils.gcd(numerator, fraction.denominator);
537        final int d2 = ArithmeticUtils.gcd(fraction.numerator, denominator);
538        return of(Math.multiplyExact(numerator / d1, fraction.numerator / d2),
539                  Math.multiplyExact(denominator / d2, fraction.denominator / d1));
540    }
541
542    /**
543     * Multiplies the fraction by an integer.
544     *
545     * @param i Value to multiply by.
546     * @return {@code this * i}.
547     */
548    @Override
549    public Fraction multiply(final int i) {
550        return multiply(of(i));
551    }
552
553    /**
554     * Divides the value of this fraction by another.
555     *
556     * @param fraction Fraction to divide by.
557     * @return a new instance.
558     * @throws ArithmeticException if the fraction to divide by is zero
559     * or if the resulting numerator or denominator cannot be represented
560     * by an {@code int}.
561     */
562    @Override
563    public Fraction divide(Fraction fraction) {
564        if (fraction.numerator == 0) {
565            throw new FractionException("the fraction to divide by must not be zero: {0}/{1}",
566                                        fraction.numerator, fraction.denominator);
567        }
568
569        return multiply(fraction.reciprocal());
570    }
571
572    /**
573     * Divides the fraction by an integer.
574     *
575     * @param i Value to divide by.
576     * @return {@code this * i}.
577     */
578    public Fraction divide(final int i) {
579        return divide(of(i));
580    }
581
582    /**
583     * @param n Power.
584     * @return <code>this<sup>n</sup></code>.
585     */
586    @Override
587    public Fraction pow(final int n) {
588        if (n == 0) {
589            return ONE;
590        }
591        if (numerator == 0) {
592            return this;
593        }
594
595        return n < 0 ?
596            new Fraction(ArithmeticUtils.pow(denominator, -n),
597                         ArithmeticUtils.pow(numerator, -n)) :
598            new Fraction(ArithmeticUtils.pow(numerator, n),
599                         ArithmeticUtils.pow(denominator, n));
600    }
601
602    /** {@inheritDoc} */
603    @Override
604    public String toString() {
605        final String str;
606        if (denominator == 1) {
607            str = Integer.toString(numerator);
608        } else if (numerator == 0) {
609            str = "0";
610        } else {
611            str = numerator + " / " + denominator;
612        }
613        return str;
614    }
615
616    /** {@inheritDoc} */
617    @Override
618    public Fraction zero() {
619        return ZERO;
620    }
621
622    /** {@inheritDoc} */
623    @Override
624    public Fraction one() {
625        return ONE;
626    }
627
628    /**
629     * Parses a string that would be produced by {@link #toString()}
630     * and instantiates the corresponding object.
631     *
632     * @param s String representation.
633     * @return an instance.
634     * @throws NumberFormatException if the string does not conform to the
635     * specification.
636     */
637    public static Fraction parse(String s) {
638        final int slashLoc = s.indexOf('/');
639        // if no slash, parse as single number
640        if (slashLoc == -1) {
641            return Fraction.of(Integer.parseInt(s.trim()));
642        } else {
643            final int num = Integer.parseInt(s.substring(0, slashLoc).trim());
644            final int denom = Integer.parseInt(s.substring(slashLoc + 1).trim());
645            return of(num, denom);
646        }
647    }
648}