All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.commons.math3.fraction.BigFraction Maven / Gradle / Ivy

Go to download

The Apache Commons Math project is a library of lightweight, self-contained mathematics and statistics components addressing the most common practical problems not immediately available in the Java programming language or commons-lang.

There is a newer version: 62
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.commons.math3.fraction;

import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;

import org.apache.commons.math3.FieldElement;
import org.apache.commons.math3.exception.MathArithmeticException;
import org.apache.commons.math3.exception.MathIllegalArgumentException;
import org.apache.commons.math3.exception.NullArgumentException;
import org.apache.commons.math3.exception.ZeroException;
import org.apache.commons.math3.exception.util.LocalizedFormats;
import org.apache.commons.math3.util.ArithmeticUtils;
import org.apache.commons.math3.util.FastMath;
import org.apache.commons.math3.util.MathUtils;

/**
 * Representation of a rational number without any overflow. This class is
 * immutable.
 *
 * @since 2.0
 */
public class BigFraction
    extends Number
    implements FieldElement, Comparable, Serializable {

    /** A fraction representing "2 / 1". */
    public static final BigFraction TWO = new BigFraction(2);

    /** A fraction representing "1". */
    public static final BigFraction ONE = new BigFraction(1);

    /** A fraction representing "0". */
    public static final BigFraction ZERO = new BigFraction(0);

    /** A fraction representing "-1 / 1". */
    public static final BigFraction MINUS_ONE = new BigFraction(-1);

    /** A fraction representing "4/5". */
    public static final BigFraction FOUR_FIFTHS = new BigFraction(4, 5);

    /** A fraction representing "1/5". */
    public static final BigFraction ONE_FIFTH = new BigFraction(1, 5);

    /** A fraction representing "1/2". */
    public static final BigFraction ONE_HALF = new BigFraction(1, 2);

    /** A fraction representing "1/4". */
    public static final BigFraction ONE_QUARTER = new BigFraction(1, 4);

    /** A fraction representing "1/3". */
    public static final BigFraction ONE_THIRD = new BigFraction(1, 3);

    /** A fraction representing "3/5". */
    public static final BigFraction THREE_FIFTHS = new BigFraction(3, 5);

    /** A fraction representing "3/4". */
    public static final BigFraction THREE_QUARTERS = new BigFraction(3, 4);

    /** A fraction representing "2/5". */
    public static final BigFraction TWO_FIFTHS = new BigFraction(2, 5);

    /** A fraction representing "2/4". */
    public static final BigFraction TWO_QUARTERS = new BigFraction(2, 4);

    /** A fraction representing "2/3". */
    public static final BigFraction TWO_THIRDS = new BigFraction(2, 3);

    /** Serializable version identifier. */
    private static final long serialVersionUID = -5630213147331578515L;

    /** BigInteger representation of 100. */
    private static final BigInteger ONE_HUNDRED = BigInteger.valueOf(100);

    /** The numerator. */
    private final BigInteger numerator;

    /** The denominator. */
    private final BigInteger denominator;

    /**
     * 

* Create a {@link BigFraction} equivalent to the passed {@code BigInteger}, ie * "num / 1". *

* * @param num * the numerator. */ public BigFraction(final BigInteger num) { this(num, BigInteger.ONE); } /** * Create a {@link BigFraction} given the numerator and denominator as * {@code BigInteger}. The {@link BigFraction} is reduced to lowest terms. * * @param num the numerator, must not be {@code null}. * @param den the denominator, must not be {@code null}. * @throws ZeroException if the denominator is zero. * @throws NullArgumentException if either of the arguments is null */ public BigFraction(BigInteger num, BigInteger den) { MathUtils.checkNotNull(num, LocalizedFormats.NUMERATOR); MathUtils.checkNotNull(den, LocalizedFormats.DENOMINATOR); if (den.signum() == 0) { throw new ZeroException(LocalizedFormats.ZERO_DENOMINATOR); } if (num.signum() == 0) { numerator = BigInteger.ZERO; denominator = BigInteger.ONE; } else { // reduce numerator and denominator by greatest common denominator final BigInteger gcd = num.gcd(den); if (BigInteger.ONE.compareTo(gcd) < 0) { num = num.divide(gcd); den = den.divide(gcd); } // move sign to numerator if (den.signum() == -1) { num = num.negate(); den = den.negate(); } // store the values in the final fields numerator = num; denominator = den; } } /** * Create a fraction given the double value. *

* This constructor behaves differently from * {@link #BigFraction(double, double, int)}. It converts the double value * exactly, considering its internal bits representation. This works for all * values except NaN and infinities and does not requires any loop or * convergence threshold. *

*

* Since this conversion is exact and since double numbers are sometimes * approximated, the fraction created may seem strange in some cases. For example, * calling new BigFraction(1.0 / 3.0) does not create * the fraction 1/3, but the fraction 6004799503160661 / 18014398509481984 * because the double number passed to the constructor is not exactly 1/3 * (this number cannot be stored exactly in IEEE754). *

* @see #BigFraction(double, double, int) * @param value the double value to convert to a fraction. * @exception MathIllegalArgumentException if value is NaN or infinite */ public BigFraction(final double value) throws MathIllegalArgumentException { if (Double.isNaN(value)) { throw new MathIllegalArgumentException(LocalizedFormats.NAN_VALUE_CONVERSION); } if (Double.isInfinite(value)) { throw new MathIllegalArgumentException(LocalizedFormats.INFINITE_VALUE_CONVERSION); } // compute m and k such that value = m * 2^k final long bits = Double.doubleToLongBits(value); final long sign = bits & 0x8000000000000000L; final long exponent = bits & 0x7ff0000000000000L; long m = bits & 0x000fffffffffffffL; if (exponent != 0) { // this was a normalized number, add the implicit most significant bit m |= 0x0010000000000000L; } if (sign != 0) { m = -m; } int k = ((int) (exponent >> 52)) - 1075; while (((m & 0x001ffffffffffffeL) != 0) && ((m & 0x1) == 0)) { m >>= 1; ++k; } if (k < 0) { numerator = BigInteger.valueOf(m); denominator = BigInteger.ZERO.flipBit(-k); } else { numerator = BigInteger.valueOf(m).multiply(BigInteger.ZERO.flipBit(k)); denominator = BigInteger.ONE; } } /** * Create a fraction given the double value and maximum error allowed. *

* References: *

*

* * @param value * the double value to convert to a fraction. * @param epsilon * maximum error allowed. The resulting fraction is within * epsilon of value, in absolute terms. * @param maxIterations * maximum number of convergents. * @throws FractionConversionException * if the continued fraction failed to converge. * @see #BigFraction(double) */ public BigFraction(final double value, final double epsilon, final int maxIterations) throws FractionConversionException { this(value, epsilon, Integer.MAX_VALUE, maxIterations); } /** * Create a fraction given the double value and either the maximum error * allowed or the maximum number of denominator digits. *

* * NOTE: This constructor is called with EITHER - a valid epsilon value and * the maxDenominator set to Integer.MAX_VALUE (that way the maxDenominator * has no effect). OR - a valid maxDenominator value and the epsilon value * set to zero (that way epsilon only has effect if there is an exact match * before the maxDenominator value is reached). *

*

* * It has been done this way so that the same code can be (re)used for both * scenarios. However this could be confusing to users if it were part of * the public API and this constructor should therefore remain PRIVATE. *

* * See JIRA issue ticket MATH-181 for more details: * * https://issues.apache.org/jira/browse/MATH-181 * * @param value * the double value to convert to a fraction. * @param epsilon * maximum error allowed. The resulting fraction is within * epsilon of value, in absolute terms. * @param maxDenominator * maximum denominator value allowed. * @param maxIterations * maximum number of convergents. * @throws FractionConversionException * if the continued fraction failed to converge. */ private BigFraction(final double value, final double epsilon, final int maxDenominator, int maxIterations) throws FractionConversionException { long overflow = Integer.MAX_VALUE; double r0 = value; long a0 = (long) FastMath.floor(r0); if (FastMath.abs(a0) > overflow) { throw new FractionConversionException(value, a0, 1l); } // check for (almost) integer arguments, which should not go // to iterations. if (FastMath.abs(a0 - value) < epsilon) { numerator = BigInteger.valueOf(a0); denominator = BigInteger.ONE; return; } long p0 = 1; long q0 = 0; long p1 = a0; long q1 = 1; long p2 = 0; long q2 = 1; int n = 0; boolean stop = false; do { ++n; final double r1 = 1.0 / (r0 - a0); final long a1 = (long) FastMath.floor(r1); p2 = (a1 * p1) + p0; q2 = (a1 * q1) + q0; if ((p2 > overflow) || (q2 > overflow)) { // in maxDenominator mode, if the last fraction was very close to the actual value // q2 may overflow in the next iteration; in this case return the last one. if (epsilon == 0.0 && FastMath.abs(q1) < maxDenominator) { break; } throw new FractionConversionException(value, p2, q2); } final double convergent = (double) p2 / (double) q2; if ((n < maxIterations) && (FastMath.abs(convergent - value) > epsilon) && (q2 < maxDenominator)) { p0 = p1; p1 = p2; q0 = q1; q1 = q2; a0 = a1; r0 = r1; } else { stop = true; } } while (!stop); if (n >= maxIterations) { throw new FractionConversionException(value, maxIterations); } if (q2 < maxDenominator) { numerator = BigInteger.valueOf(p2); denominator = BigInteger.valueOf(q2); } else { numerator = BigInteger.valueOf(p1); denominator = BigInteger.valueOf(q1); } } /** * Create a fraction given the double value and maximum denominator. *

* References: *

*

* * @param value * the double value to convert to a fraction. * @param maxDenominator * The maximum allowed value for denominator. * @throws FractionConversionException * if the continued fraction failed to converge. */ public BigFraction(final double value, final int maxDenominator) throws FractionConversionException { this(value, 0, maxDenominator, 100); } /** *

* Create a {@link BigFraction} equivalent to the passed {@code int}, ie * "num / 1". *

* * @param num * the numerator. */ public BigFraction(final int num) { this(BigInteger.valueOf(num), BigInteger.ONE); } /** *

* Create a {@link BigFraction} given the numerator and denominator as simple * {@code int}. The {@link BigFraction} is reduced to lowest terms. *

* * @param num * the numerator. * @param den * the denominator. */ public BigFraction(final int num, final int den) { this(BigInteger.valueOf(num), BigInteger.valueOf(den)); } /** *

* Create a {@link BigFraction} equivalent to the passed long, ie "num / 1". *

* * @param num * the numerator. */ public BigFraction(final long num) { this(BigInteger.valueOf(num), BigInteger.ONE); } /** *

* Create a {@link BigFraction} given the numerator and denominator as simple * {@code long}. The {@link BigFraction} is reduced to lowest terms. *

* * @param num * the numerator. * @param den * the denominator. */ public BigFraction(final long num, final long den) { this(BigInteger.valueOf(num), BigInteger.valueOf(den)); } /** *

* Creates a BigFraction instance with the 2 parts of a fraction * Y/Z. *

* *

* Any negative signs are resolved to be on the numerator. *

* * @param numerator * the numerator, for example the three in 'three sevenths'. * @param denominator * the denominator, for example the seven in 'three sevenths'. * @return a new fraction instance, with the numerator and denominator * reduced. * @throws ArithmeticException * if the denominator is zero. */ public static BigFraction getReducedFraction(final int numerator, final int denominator) { if (numerator == 0) { return ZERO; // normalize zero. } return new BigFraction(numerator, denominator); } /** *

* Returns the absolute value of this {@link BigFraction}. *

* * @return the absolute value as a {@link BigFraction}. */ public BigFraction abs() { return (numerator.signum() == 1) ? this : negate(); } /** *

* Adds the value of this fraction to the passed {@link BigInteger}, * returning the result in reduced form. *

* * @param bg * the {@link BigInteger} to add, must'nt be null. * @return a BigFraction instance with the resulting values. * @throws NullArgumentException * if the {@link BigInteger} is null. */ public BigFraction add(final BigInteger bg) throws NullArgumentException { MathUtils.checkNotNull(bg); if (numerator.signum() == 0) { return new BigFraction(bg); } if (bg.signum() == 0) { return this; } return new BigFraction(numerator.add(denominator.multiply(bg)), denominator); } /** *

* Adds the value of this fraction to the passed {@code integer}, returning * the result in reduced form. *

* * @param i * the {@code integer} to add. * @return a BigFraction instance with the resulting values. */ public BigFraction add(final int i) { return add(BigInteger.valueOf(i)); } /** *

* Adds the value of this fraction to the passed {@code long}, returning * the result in reduced form. *

* * @param l * the {@code long} to add. * @return a BigFraction instance with the resulting values. */ public BigFraction add(final long l) { return add(BigInteger.valueOf(l)); } /** *

* Adds the value of this fraction to another, returning the result in * reduced form. *

* * @param fraction * the {@link BigFraction} to add, must not be null. * @return a {@link BigFraction} instance with the resulting values. * @throws NullArgumentException if the {@link BigFraction} is {@code null}. */ public BigFraction add(final BigFraction fraction) { if (fraction == null) { throw new NullArgumentException(LocalizedFormats.FRACTION); } if (fraction.numerator.signum() == 0) { return this; } if (numerator.signum() == 0) { return fraction; } BigInteger num = null; BigInteger den = null; if (denominator.equals(fraction.denominator)) { num = numerator.add(fraction.numerator); den = denominator; } else { num = (numerator.multiply(fraction.denominator)).add((fraction.numerator).multiply(denominator)); den = denominator.multiply(fraction.denominator); } if (num.signum() == 0) { return ZERO; } return new BigFraction(num, den); } /** *

* Gets the fraction as a BigDecimal. This calculates the * fraction as the numerator divided by denominator. *

* * @return the fraction as a BigDecimal. * @throws ArithmeticException * if the exact quotient does not have a terminating decimal * expansion. * @see BigDecimal */ public BigDecimal bigDecimalValue() { return new BigDecimal(numerator).divide(new BigDecimal(denominator)); } /** *

* Gets the fraction as a BigDecimal following the passed * rounding mode. This calculates the fraction as the numerator divided by * denominator. *

* * @param roundingMode * rounding mode to apply. see {@link BigDecimal} constants. * @return the fraction as a BigDecimal. * @throws IllegalArgumentException * if {@code roundingMode} does not represent a valid rounding * mode. * @see BigDecimal */ public BigDecimal bigDecimalValue(final int roundingMode) { return new BigDecimal(numerator).divide(new BigDecimal(denominator), roundingMode); } /** *

* Gets the fraction as a BigDecimal following the passed scale * and rounding mode. This calculates the fraction as the numerator divided * by denominator. *

* * @param scale * scale of the BigDecimal quotient to be returned. * see {@link BigDecimal} for more information. * @param roundingMode * rounding mode to apply. see {@link BigDecimal} constants. * @return the fraction as a BigDecimal. * @see BigDecimal */ public BigDecimal bigDecimalValue(final int scale, final int roundingMode) { return new BigDecimal(numerator).divide(new BigDecimal(denominator), scale, roundingMode); } /** *

* Compares this object to another based on size. *

* * @param object * the object to compare to, must not be null. * @return -1 if this is less than {@code object}, +1 if this is greater * than {@code object}, 0 if they are equal. * @see java.lang.Comparable#compareTo(java.lang.Object) */ public int compareTo(final BigFraction object) { int lhsSigNum = numerator.signum(); int rhsSigNum = object.numerator.signum(); if (lhsSigNum != rhsSigNum) { return (lhsSigNum > rhsSigNum) ? 1 : -1; } if (lhsSigNum == 0) { return 0; } BigInteger nOd = numerator.multiply(object.denominator); BigInteger dOn = denominator.multiply(object.numerator); return nOd.compareTo(dOn); } /** *

* Divide the value of this fraction by the passed {@code BigInteger}, * ie {@code this * 1 / bg}, returning the result in reduced form. *

* * @param bg the {@code BigInteger} to divide by, must not be {@code null} * @return a {@link BigFraction} instance with the resulting values * @throws NullArgumentException if the {@code BigInteger} is {@code null} * @throws MathArithmeticException if the fraction to divide by is zero */ public BigFraction divide(final BigInteger bg) { if (bg == null) { throw new NullArgumentException(LocalizedFormats.FRACTION); } if (bg.signum() == 0) { throw new MathArithmeticException(LocalizedFormats.ZERO_DENOMINATOR); } if (numerator.signum() == 0) { return ZERO; } return new BigFraction(numerator, denominator.multiply(bg)); } /** *

* Divide the value of this fraction by the passed {@code int}, ie * {@code this * 1 / i}, returning the result in reduced form. *

* * @param i the {@code int} to divide by * @return a {@link BigFraction} instance with the resulting values * @throws MathArithmeticException if the fraction to divide by is zero */ public BigFraction divide(final int i) { return divide(BigInteger.valueOf(i)); } /** *

* Divide the value of this fraction by the passed {@code long}, ie * {@code this * 1 / l}, returning the result in reduced form. *

* * @param l the {@code long} to divide by * @return a {@link BigFraction} instance with the resulting values * @throws MathArithmeticException if the fraction to divide by is zero */ public BigFraction divide(final long l) { return divide(BigInteger.valueOf(l)); } /** *

* Divide the value of this fraction by another, returning the result in * reduced form. *

* * @param fraction Fraction to divide by, must not be {@code null}. * @return a {@link BigFraction} instance with the resulting values. * @throws NullArgumentException if the {@code fraction} is {@code null}. * @throws MathArithmeticException if the fraction to divide by is zero */ public BigFraction divide(final BigFraction fraction) { if (fraction == null) { throw new NullArgumentException(LocalizedFormats.FRACTION); } if (fraction.numerator.signum() == 0) { throw new MathArithmeticException(LocalizedFormats.ZERO_DENOMINATOR); } if (numerator.signum() == 0) { return ZERO; } return multiply(fraction.reciprocal()); } /** *

* Gets the fraction as a {@code double}. This calculates the fraction as * the numerator divided by denominator. *

* * @return the fraction as a {@code double} * @see java.lang.Number#doubleValue() */ @Override public double doubleValue() { double result = numerator.doubleValue() / denominator.doubleValue(); if (Double.isNaN(result)) { // Numerator and/or denominator must be out of range: // Calculate how far to shift them to put them in range. int shift = FastMath.max(numerator.bitLength(), denominator.bitLength()) - FastMath.getExponent(Double.MAX_VALUE); result = numerator.shiftRight(shift).doubleValue() / denominator.shiftRight(shift).doubleValue(); } return result; } /** *

* Test for the equality of two fractions. If the lowest term numerator and * denominators are the same for both fractions, the two fractions are * considered to be equal. *

* * @param other * fraction to test for equality to this fraction, can be * null. * @return true if two fractions are equal, false if object is * null, not an instance of {@link BigFraction}, or not * equal to this fraction instance. * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(final Object other) { boolean ret = false; if (this == other) { ret = true; } else if (other instanceof BigFraction) { BigFraction rhs = ((BigFraction) other).reduce(); BigFraction thisOne = this.reduce(); ret = thisOne.numerator.equals(rhs.numerator) && thisOne.denominator.equals(rhs.denominator); } return ret; } /** *

* Gets the fraction as a {@code float}. This calculates the fraction as * the numerator divided by denominator. *

* * @return the fraction as a {@code float}. * @see java.lang.Number#floatValue() */ @Override public float floatValue() { float result = numerator.floatValue() / denominator.floatValue(); if (Double.isNaN(result)) { // Numerator and/or denominator must be out of range: // Calculate how far to shift them to put them in range. int shift = FastMath.max(numerator.bitLength(), denominator.bitLength()) - FastMath.getExponent(Float.MAX_VALUE); result = numerator.shiftRight(shift).floatValue() / denominator.shiftRight(shift).floatValue(); } return result; } /** *

* Access the denominator as a BigInteger. *

* * @return the denominator as a BigInteger. */ public BigInteger getDenominator() { return denominator; } /** *

* Access the denominator as a {@code int}. *

* * @return the denominator as a {@code int}. */ public int getDenominatorAsInt() { return denominator.intValue(); } /** *

* Access the denominator as a {@code long}. *

* * @return the denominator as a {@code long}. */ public long getDenominatorAsLong() { return denominator.longValue(); } /** *

* Access the numerator as a BigInteger. *

* * @return the numerator as a BigInteger. */ public BigInteger getNumerator() { return numerator; } /** *

* Access the numerator as a {@code int}. *

* * @return the numerator as a {@code int}. */ public int getNumeratorAsInt() { return numerator.intValue(); } /** *

* Access the numerator as a {@code long}. *

* * @return the numerator as a {@code long}. */ public long getNumeratorAsLong() { return numerator.longValue(); } /** *

* Gets a hashCode for the fraction. *

* * @return a hash code value for this object. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return 37 * (37 * 17 + numerator.hashCode()) + denominator.hashCode(); } /** *

* Gets the fraction as an {@code int}. This returns the whole number part * of the fraction. *

* * @return the whole number fraction part. * @see java.lang.Number#intValue() */ @Override public int intValue() { return numerator.divide(denominator).intValue(); } /** *

* Gets the fraction as a {@code long}. This returns the whole number part * of the fraction. *

* * @return the whole number fraction part. * @see java.lang.Number#longValue() */ @Override public long longValue() { return numerator.divide(denominator).longValue(); } /** *

* Multiplies the value of this fraction by the passed * BigInteger, returning the result in reduced form. *

* * @param bg the {@code BigInteger} to multiply by. * @return a {@code BigFraction} instance with the resulting values. * @throws NullArgumentException if {@code bg} is {@code null}. */ public BigFraction multiply(final BigInteger bg) { if (bg == null) { throw new NullArgumentException(); } if (numerator.signum() == 0 || bg.signum() == 0) { return ZERO; } return new BigFraction(bg.multiply(numerator), denominator); } /** *

* Multiply the value of this fraction by the passed {@code int}, returning * the result in reduced form. *

* * @param i * the {@code int} to multiply by. * @return a {@link BigFraction} instance with the resulting values. */ public BigFraction multiply(final int i) { if (i == 0 || numerator.signum() == 0) { return ZERO; } return multiply(BigInteger.valueOf(i)); } /** *

* Multiply the value of this fraction by the passed {@code long}, * returning the result in reduced form. *

* * @param l * the {@code long} to multiply by. * @return a {@link BigFraction} instance with the resulting values. */ public BigFraction multiply(final long l) { if (l == 0 || numerator.signum() == 0) { return ZERO; } return multiply(BigInteger.valueOf(l)); } /** *

* Multiplies the value of this fraction by another, returning the result in * reduced form. *

* * @param fraction Fraction to multiply by, must not be {@code null}. * @return a {@link BigFraction} instance with the resulting values. * @throws NullArgumentException if {@code fraction} is {@code null}. */ public BigFraction multiply(final BigFraction fraction) { if (fraction == null) { throw new NullArgumentException(LocalizedFormats.FRACTION); } if (numerator.signum() == 0 || fraction.numerator.signum() == 0) { return ZERO; } return new BigFraction(numerator.multiply(fraction.numerator), denominator.multiply(fraction.denominator)); } /** *

* Return the additive inverse of this fraction, returning the result in * reduced form. *

* * @return the negation of this fraction. */ public BigFraction negate() { return new BigFraction(numerator.negate(), denominator); } /** *

* Gets the fraction percentage as a {@code double}. This calculates the * fraction as the numerator divided by denominator multiplied by 100. *

* * @return the fraction percentage as a {@code double}. */ public double percentageValue() { return multiply(ONE_HUNDRED).doubleValue(); } /** *

* Returns a {@code BigFraction} whose value is * {@code (thisexponent)}, returning the result in reduced form. *

* * @param exponent * exponent to which this {@code BigFraction} is to be * raised. * @return thisexponent. */ public BigFraction pow(final int exponent) { if (exponent == 0) { return ONE; } if (numerator.signum() == 0) { return this; } if (exponent < 0) { return new BigFraction(denominator.pow(-exponent), numerator.pow(-exponent)); } return new BigFraction(numerator.pow(exponent), denominator.pow(exponent)); } /** *

* Returns a BigFraction whose value is * (thisexponent), returning the result in reduced form. *

* * @param exponent * exponent to which this BigFraction is to be raised. * @return thisexponent as a BigFraction. */ public BigFraction pow(final long exponent) { if (exponent == 0) { return ONE; } if (numerator.signum() == 0) { return this; } if (exponent < 0) { return new BigFraction(ArithmeticUtils.pow(denominator, -exponent), ArithmeticUtils.pow(numerator, -exponent)); } return new BigFraction(ArithmeticUtils.pow(numerator, exponent), ArithmeticUtils.pow(denominator, exponent)); } /** *

* Returns a BigFraction whose value is * (thisexponent), returning the result in reduced form. *

* * @param exponent * exponent to which this BigFraction is to be raised. * @return thisexponent as a BigFraction. */ public BigFraction pow(final BigInteger exponent) { if (exponent.signum() == 0) { return ONE; } if (numerator.signum() == 0) { return this; } if (exponent.signum() == -1) { final BigInteger eNeg = exponent.negate(); return new BigFraction(ArithmeticUtils.pow(denominator, eNeg), ArithmeticUtils.pow(numerator, eNeg)); } return new BigFraction(ArithmeticUtils.pow(numerator, exponent), ArithmeticUtils.pow(denominator, exponent)); } /** *

* Returns a double whose value is * (thisexponent), returning the result in reduced form. *

* * @param exponent * exponent to which this BigFraction is to be raised. * @return thisexponent. */ public double pow(final double exponent) { return FastMath.pow(numerator.doubleValue(), exponent) / FastMath.pow(denominator.doubleValue(), exponent); } /** *

* Return the multiplicative inverse of this fraction. *

* * @return the reciprocal fraction. */ public BigFraction reciprocal() { return new BigFraction(denominator, numerator); } /** *

* Reduce this BigFraction to its lowest terms. *

* * @return the reduced BigFraction. It doesn't change anything if * the fraction can be reduced. */ public BigFraction reduce() { final BigInteger gcd = numerator.gcd(denominator); if (BigInteger.ONE.compareTo(gcd) < 0) { return new BigFraction(numerator.divide(gcd), denominator.divide(gcd)); } else { return this; } } /** *

* Subtracts the value of an {@link BigInteger} from the value of this * {@code BigFraction}, returning the result in reduced form. *

* * @param bg the {@link BigInteger} to subtract, cannot be {@code null}. * @return a {@code BigFraction} instance with the resulting values. * @throws NullArgumentException if the {@link BigInteger} is {@code null}. */ public BigFraction subtract(final BigInteger bg) { if (bg == null) { throw new NullArgumentException(); } if (bg.signum() == 0) { return this; } if (numerator.signum() == 0) { return new BigFraction(bg.negate()); } return new BigFraction(numerator.subtract(denominator.multiply(bg)), denominator); } /** *

* Subtracts the value of an {@code integer} from the value of this * {@code BigFraction}, returning the result in reduced form. *

* * @param i the {@code integer} to subtract. * @return a {@code BigFraction} instance with the resulting values. */ public BigFraction subtract(final int i) { return subtract(BigInteger.valueOf(i)); } /** *

* Subtracts the value of a {@code long} from the value of this * {@code BigFraction}, returning the result in reduced form. *

* * @param l the {@code long} to subtract. * @return a {@code BigFraction} instance with the resulting values. */ public BigFraction subtract(final long l) { return subtract(BigInteger.valueOf(l)); } /** *

* Subtracts the value of another fraction from the value of this one, * returning the result in reduced form. *

* * @param fraction {@link BigFraction} to subtract, must not be {@code null}. * @return a {@link BigFraction} instance with the resulting values * @throws NullArgumentException if the {@code fraction} is {@code null}. */ public BigFraction subtract(final BigFraction fraction) { if (fraction == null) { throw new NullArgumentException(LocalizedFormats.FRACTION); } if (fraction.numerator.signum() == 0) { return this; } if (numerator.signum() == 0) { return fraction.negate(); } BigInteger num = null; BigInteger den = null; if (denominator.equals(fraction.denominator)) { num = numerator.subtract(fraction.numerator); den = denominator; } else { num = (numerator.multiply(fraction.denominator)).subtract((fraction.numerator).multiply(denominator)); den = denominator.multiply(fraction.denominator); } return new BigFraction(num, den); } /** *

* Returns the String representing this fraction, ie * "num / dem" or just "num" if the denominator is one. *

* * @return a string representation of the fraction. * @see java.lang.Object#toString() */ @Override public String toString() { String str = null; if (BigInteger.ONE.equals(denominator)) { str = numerator.toString(); } else if (BigInteger.ZERO.equals(numerator)) { str = "0"; } else { str = numerator + " / " + denominator; } return str; } /** {@inheritDoc} */ public BigFractionField getField() { return BigFractionField.getInstance(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy