fraction.java

来自「JAVA 文章管理系统源码」· Java 代码 · 共 795 行 · 第 1/2 页

JAVA
795
字号
     * <p>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.</p>
     *
     * @return the numerator fraction part of a proper fraction, always positive
     */
    public int getProperNumerator() {
        return Math.abs(numerator % denominator);
    }

    /**
     * <p>Gets the proper whole part of the fraction.</p>
     *
     * <p>An improper fraction 7/4 can be resolved into a proper one, 1 3/4.
     * This method returns the 1 from the proper fraction.</p>
     *
     * <p>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.</p>
     *
     * @return the whole fraction part of a proper fraction, that includes the sign
     */
    public int getProperWhole() {
        return numerator / denominator;
    }

    // Number methods
    //-------------------------------------------------------------------

    /**
     * <p>Gets the fraction as an <code>int</code>. This returns the whole number
     * part of the fraction.</p>
     *
     * @return the whole number fraction part
     */
    public int intValue() {
        return numerator / denominator;
    }

    /**
     * <p>Gets the fraction as a <code>long</code>. This returns the whole number
     * part of the fraction.</p>
     *
     * @return the whole number fraction part
     */
    public long longValue() {
        return (long) numerator / denominator;
    }

    /**
     * <p>Gets the fraction as a <code>float</code>. This calculates the fraction
     * as the numerator divided by denominator.</p>
     *
     * @return the fraction as a <code>float</code>
     */
    public float floatValue() {
        return ((float) numerator) / ((float) denominator);
    }

    /**
     * <p>Gets the fraction as a <code>double</code>. This calculates the fraction
     * as the numerator divided by denominator.</p>
     *
     * @return the fraction as a <code>double</code>
     */
    public double doubleValue() {
        return ((double) numerator) / ((double) denominator);
    }

    // Calculations
    //-------------------------------------------------------------------

    /**
     * <p>Reduce the fraction to the smallest values for the numerator and
     * denominator, returning the result..</p>
     *
     * @return a new reduce fraction instance, or this if no simplification possible
     */
    public Fraction reduce() {
        int gcd = greatestCommonDivisor(Math.abs(numerator), denominator);
        return Fraction.getFraction(numerator / gcd, denominator / gcd);
    }

    /**
     * <p>Gets a fraction that is the invert (1/fraction) of this one.</p>
     *
     * <p>The returned fraction is not reduced.</p>
     *
     * @return a new fraction instance with the numerator and denominator inverted
     * @throws ArithmeticException if the numerator is <code>zero</code>
     */
    public Fraction invert() {
        if (numerator == 0) {
            throw new ArithmeticException("Unable to invert a fraction with a zero numerator");
        }
        return getFraction(denominator, numerator);
    }

    /**
     * <p>Gets a fraction that is the negative (-fraction) of this one.</p>
     *
     * <p>The returned fraction is not reduced.</p>
     *
     * @return a new fraction instance with the opposite signed numerator
     */
    public Fraction negate() {
        return getFraction(-numerator, denominator);
    }

    /**
     * <p>Gets a fraction that is the positive equivalent of this one.</p>
     * <p>More precisely: <pre>(fraction >= 0 ? this : -fraction)</pre></p>
     *
     * <p>The returned fraction is not reduced.</p>
     *
     * @return <code>this</code> if it is positive, or a new positive fraction
     *  instance with the opposite signed numerator
     */
    public Fraction abs() {
        if (numerator >= 0) {
            return this;
        }
        return getFraction(-numerator, denominator);
    }

    /**
     * <p>Gets a fraction that is raised to the passed in power.</p>
     *
     * <p>The returned fraction is not reduced.</p>
     *
     * @param power  the power to raise the fraction to
     * @return <code>this</code> if the power is one, <code>ONE</code> if the power
     * is zero (even if the fraction equals ZERO) or a new fraction instance 
     * raised to the appropriate power
     * @throws ArithmeticException if the resulting numerator or denominator exceeds
     *  <code>Integer.MAX_VALUE</code>
     */
    public Fraction pow(int power) {
        if (power == 1) {
            return this;
        } else if (power == 0) {
            return ONE;
        } else {
            double denominatorValue = Math.pow(denominator, power);
            double numeratorValue = Math.pow(numerator, power);
            if (numeratorValue > Integer.MAX_VALUE || denominatorValue > Integer.MAX_VALUE) {
                throw new ArithmeticException("Integer overflow");
            }
            if (power < 0) {
                return getFraction((int) Math.pow(denominator, -power), 
                    (int) Math.pow(numerator, -power));
            }
            return getFraction((int) Math.pow(numerator, power), 
                (int) Math.pow(denominator, power));
        }
    }

    /**
     * <p>Gets the greatest common divisor of two numbers.</p>
     *
     * @param number1  a positive number
     * @param number2  a positive number
     * @return the greatest common divisor, never zero
     */
    private static int greatestCommonDivisor(int number1, int number2) {
        int remainder = number1 % number2;
        while (remainder != 0) {
            number1 = number2;
            number2 = remainder;
            remainder = number1 % number2;
        }
        return number2;
    }

    // Arithmetic
    //-------------------------------------------------------------------

    /**
     * <p>Adds the value of this fraction to another, returning the result in 
     * reduced form.</p>
     *
     * @param fraction  the fraction to add, must not be <code>null</code>
     * @return a <code>Fraction</code> instance with the resulting values
     * @throws IllegalArgumentException if the fraction is <code>null</code>
     * @throws ArithmeticException if the resulting numerator or denominator exceeds
     *  <code>Integer.MAX_VALUE</code>
     */
    public Fraction add(Fraction fraction) {
        if (fraction == null) {
            throw new IllegalArgumentException("The fraction must not be null");
        }
        if (numerator == 0) {
            return fraction;
        }
        if (fraction.numerator == 0) {
            return this;
        }     
        // Compute lcd explicitly to limit overflow
        int gcd = greatestCommonDivisor(Math.abs(fraction.denominator), Math.abs(denominator));
        int thisResidue = denominator/gcd;
        int thatResidue = fraction.denominator/gcd;
        double denominatorValue = Math.abs((double) gcd * thisResidue * thatResidue);
        double numeratorValue = (double) numerator * thatResidue + fraction.numerator * thisResidue;
        if (Math.abs(numeratorValue) > Integer.MAX_VALUE || 
            Math.abs(denominatorValue) > Integer.MAX_VALUE) {
                throw new ArithmeticException("Integer overflow");
        }
        return Fraction.getReducedFraction((int) numeratorValue, (int) denominatorValue);
    }

    /**
     * <p>Subtracts the value of another fraction from the value of this one,
     * returning the result in reduced form.</p>
     *
     * @param fraction  the fraction to subtract, must not be <code>null</code>
     * @return a <code>Fraction</code> instance with the resulting values
     * @throws IllegalArgumentException if the fraction is <code>null</code>
     * @throws ArithmeticException if the resulting numerator or denominator exceeds
     *  <code>Integer.MAX_VALUE</code>
     */
    public Fraction subtract(Fraction fraction) {
        if (fraction == null) {
            throw new IllegalArgumentException("The fraction must not be null");
        }
        return add(fraction.negate());
    }

    /**
     * <p>Multiplies the value of this fraction by another, returning the result 
     * in reduced form.</p>
     *
     * @param fraction  the fraction to multipy by, must not be <code>null</code>
     * @return a <code>Fraction</code> instance with the resulting values
     * @throws IllegalArgumentException if the fraction is <code>null</code>
     * @throws ArithmeticException if the resulting numerator or denominator exceeds
     *  <code>Integer.MAX_VALUE</code>
     */
    public Fraction multiplyBy(Fraction fraction) {
        if (fraction == null) {
            throw new IllegalArgumentException("The fraction must not be null");
        }
        if (numerator == 0 || fraction.numerator == 0) {
            return ZERO;
        }
        double numeratorValue = (double) numerator * fraction.numerator;
        double denominatorValue = (double) denominator * fraction.denominator;
        if (Math.abs(numeratorValue) > Integer.MAX_VALUE || 
            Math.abs(denominatorValue) > Integer.MAX_VALUE) {
                throw new ArithmeticException("Integer overflow");
        }
        return getReducedFraction((int) numeratorValue, (int) denominatorValue);
    }

    /**
     * <p>Divide the value of this fraction by another, returning the result 
     * in reduced form.</p>
     *
     * @param fraction  the fraction to divide by, must not be <code>null</code>
     * @return a <code>Fraction</code> instance with the resulting values
     * @throws IllegalArgumentException if the fraction is <code>null</code>
     * @throws ArithmeticException if the fraction to divide by is zero
     * @throws ArithmeticException if the resulting numerator or denominator exceeds
     *  <code>Integer.MAX_VALUE</code>
     */
    public Fraction divideBy(Fraction fraction) {
        if (fraction == null) {
            throw new IllegalArgumentException("The fraction must not be null");
        }
        if (fraction.numerator == 0) {
            throw new ArithmeticException("The fraction to divide by must not be zero");
        }
        if (numerator == 0) {
            return ZERO;
        }  
        double numeratorValue = (double) numerator * fraction.denominator;
        double denominatorValue = (double) denominator * fraction.numerator;
        if (Math.abs(numeratorValue) > Integer.MAX_VALUE || 
            Math.abs(denominatorValue) > Integer.MAX_VALUE) {
                throw new ArithmeticException("Integer overflow");
        }
        return getReducedFraction((int) numeratorValue, (int) denominatorValue);
    }

    // Basics
    //-------------------------------------------------------------------

    /**
     * <p>Compares this fraction to another object to test if they are equal.</p>.
     *
     * <p>To be equal, both values must be equal. Thus 2/4 is not equal to 1/2.</p>
     *
     * @param obj the reference object with which to compare
     * @return <code>true</code> if this object is equal
     */
    public boolean equals(Object obj) {
        if (obj == this) {
            return true;
        }
        if (obj instanceof Fraction == false) {
            return false;
        }
        Fraction other = (Fraction) obj;
        return (numerator == other.numerator &&
                denominator == other.denominator);
    }

    /**
     * <p>Gets a hashCode for the fraction.</p>
     *
     * @return a hash code value for this object
     */
    public int hashCode() {
        if (hashCode == 0) {
            hashCode = 17;
            hashCode = 37 * hashCode + numerator;
            hashCode = 37 * hashCode + denominator;
        }
        return hashCode;
    }

    /**
     * <p>Compares this object to another based on size.</p>
     *
     * @param object  the object to compare to
     * @return -1 if this is less, 0 if equal, +1 if greater
     * @throws ClassCastException if the object is not a <code>Fraction</code>
     * @throws NullPointerException if the object is <code>null</code>
     */
    public int compareTo(Object object) {
        Fraction other = (Fraction) object;
        if (numerator == other.numerator && denominator == other.denominator) {
            return 0;
        }

        // otherwise see which is less
        long first = (long) numerator * (long) other.denominator;
        long second = (long) other.numerator * (long) denominator;
        if (first == second) {
            return 0;
        } else if (first < second) {
            return -1;
        } else {
            return 1;
        }
    }

    /**
     * <p>Gets the fraction as a <code>String</code>.</p>
     *
     * <p>The format used is '<i>numerator</i>/<i>denominator</i>' always.
     *
     * @return a <code>String</code> form of the fraction
     */
    public String toString() {
        if (toString == null) {
            toString = new StringBuffer(32)
                .append(numerator)
                .append('/')
                .append(denominator).toString();
        }
        return toString;
    }

    /**
     * <p>Gets the fraction as a proper <code>String</code> in the format X Y/Z.</p>
     *
     * <p>The format used in '<i>wholeNumber</i> <i>numerator</i>/<i>denominator</i>'.
     * If the whole number is zero it will be ommitted. If the numerator is zero,
     * only the whole number is returned.</p>
     *
     * @return a <code>String</code> form of the fraction
     */
    public String toProperString() {
        if (toProperString == null) {
            if (numerator == 0) {
                toProperString = "0";
            } else if (numerator == denominator) {
                toProperString = "1";
            } else if (Math.abs(numerator) > denominator) {
                int properNumerator = getProperNumerator();
                if (properNumerator == 0) {
                    toProperString = Integer.toString(getProperWhole());
                } else {
                    toProperString = new StringBuffer(32)
                        .append(getProperWhole()).append(' ')
                        .append(properNumerator).append('/')
                        .append(denominator).toString();
                }
            } else {
                toProperString = new StringBuffer(32)
                    .append(numerator).append('/')
                    .append(denominator).toString();
            }
        }
        return toProperString;
    }

}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?