All pastes #1393898 Raw Edit

Fraction class

public java v1 · immutable
#1393898 ·published 2009-04-16 14:03 UTC
rendered paste body
package net.cynthia;/** * An immutable class containing a fraction. Operations in this class return a * new <tt>Fraction</tt> containing their result; they do not modify any * original <tt>Fraction</tt>. * <p> * Operations supported by objects of this class are: * <ul> * <li>addition to a fraction or a number; * <li>subtraction of a fraction or a number; * <li>multiplication by a fraction or a number; * <li>division by a fraction or a number. * </ul> *  * @author Cynthia G. */public class Fraction implements java.io.Serializable, Comparable<Fraction> {	private static final long serialVersionUID = 1L;	/**	 * The numerator of this <tt>Fraction</tt>.	 */	private final long numerator;	/**	 * The denominator of this <tt>Fraction</tt>.	 */	private final long denominator;	/**	 * Constructs a <tt>Fraction</tt> representing the value 0. The	 * denominator does not matter, but this constructor sets it to 1.	 */	public Fraction() {		this(0L);	}	/**	 * Constructs a <tt>Fraction</tt> having the given <code>numerator</code>	 * and a <code>denominator</code> of 1.	 * 	 * @param numerator	 *            The numerator of the newly created <tt>Fraction</tt>.	 */	public Fraction(final long numerator) {		this.numerator = numerator;		denominator = 1L;	}	/**	 * Constructs a <tt>Fraction</tt> having the given <code>numerator</code>	 * and <code>denominator</code>.	 * 	 * @param numerator	 *            The numerator of the newly created <tt>Fraction</tt>.	 * @param denominator	 *            The denominator of the newly created <tt>Fraction</tt>.	 */	public Fraction(final long numerator, final long denominator) {		if (denominator >= 0) {			this.numerator = numerator;			this.denominator = denominator;		} else {			this.numerator = -numerator;			this.denominator = -denominator;		}	}	/**	 * Size of the cache of <tt>Fraction</tt>s maintained by this class, of	 * either sign.	 */	private static final int CACHE_SIZE = 100;	private static final Fraction[] CACHE = new Fraction[CACHE_SIZE * 2];	static {		for (int i = -CACHE_SIZE; i < CACHE_SIZE; i++)			CACHE[i + CACHE_SIZE] = new Fraction(i);	}	/**	 * Returns a <tt>Fraction</tt> whose numerator is the given	 * <code>number</code> and whose denominator is 1. Calling this method may	 * be more efficient than creating <tt>Fraction</tt>s on demand, since	 * frequently-used values may be cached.	 * 	 * @param number	 *            The number to use as the returned <tt>Fraction</tt>'s	 *            numerator.	 * @return a <tt>Fraction</tt> whose numerator is the given	 *         <code>number</code> and whose denominator is 1	 */	public static Fraction valueOf(final long number) {		if (number >= -CACHE_SIZE && number < CACHE_SIZE)			return CACHE[(int) (number + CACHE_SIZE)];		return new Fraction(number);	}	/**	 * Returns the numerator of this <tt>Fraction</tt>. The numerator is the	 * integer above the division bar in a fraction when written out.	 * 	 * @return the numerator of this <tt>Fraction</tt>	 */	public long getNumerator() {		return numerator;	}	/**	 * Returns the denominator of this <tt>Fraction</tt>. The denominator is	 * the integer below the division bar in a fraction when written out. It is	 * never negative, but may be 0.	 * 	 * @return the denominator of this <tt>Fraction</tt>	 */	public long getDenominator() {		return denominator;	}	/**	 * Adds this <tt>Fraction</tt> and the <code>other</code> one together,	 * then returns the result of that addition.	 * 	 * @param other	 *            The <tt>Fraction</tt> to add to this one.	 * @return the result of the addition of this <tt>Fraction</tt> and the	 *         <code>other</code> one	 */	public Fraction add(final Fraction other) {		// If the denominator of either fraction is 0, return ?/0.		if (denominator == 0 || other.denominator == 0)			return new Fraction(0, 0);		final long denominator;		// If the denominators are already the same,		if (this.denominator == other.denominator)			// use it as the denominator of the resulting fraction.			denominator = this.denominator;		// If the denominator of one divides that of the other evenly,		// use the greater one.		else if (this.denominator % other.denominator == 0)			denominator = this.denominator;		else if (other.denominator % this.denominator == 0)			denominator = other.denominator;		// Otherwise, just multiply both.		else			denominator = this.denominator * other.denominator;		final long numerator = this.numerator				* (denominator / this.denominator) + other.numerator				* (denominator / other.denominator);		return new Fraction(numerator, denominator);	}	/**	 * Adds this <tt>Fraction</tt> and the given <code>number</code>	 * together, then returns the result of that addition.	 * 	 * @param number	 *            The number to add to this <tt>Fraction</tt>.	 * @return the result of the addition of this <tt>Fraction</tt> and the	 *         given <code>number</code>	 */	public Fraction add(final long number) {		return add(valueOf(number));	}	/**	 * Subtracts the <code>other</code> <tt>Fraction</tt> from this one,	 * then returns the result of that subtraction.	 * 	 * @param other	 *            The <tt>Fraction</tt> to subtract from this one.	 * @return the result of the subtraction of the	 *         <code>other</code> <tt>Fraction</tt> from this one	 */	public Fraction subtract(final Fraction other) {		return add(other.negate());	}	/**	 * Subtracts the given <code>number</code> from this <tt>Fraction</tt>,	 * then returns the result of that subtraction.	 * 	 * @param number	 *            The number to subtract from this <tt>Fraction</tt>.	 * @return the result of the subtraction of the given <code>number</code>	 *         from this <tt>Fraction</tt>	 */	public Fraction subtract(final long number) {		return subtract(valueOf(number));	}	/**	 * Multiplies this <tt>Fraction</tt> by the <code>other</code> one, then	 * returns the result of that multiplication.	 * 	 * @param other	 *            The <tt>Fraction</tt> to multiply this one by.	 * @return the result of the multiplication of this <tt>Fraction</tt> by	 *         the <code>other</code> one	 */	public Fraction multiply(final Fraction other) {		return new Fraction(numerator * other.numerator, denominator				* other.denominator);	}	/**	 * Multiplies this <tt>Fraction</tt> by the given <code>number</code>,	 * then returns the result of that multiplication.	 * 	 * @param number	 *            The number to multiply this <tt>Fraction</tt> by.	 * @return the result of the multiplication of this <tt>Fraction</tt> by	 *         the given <code>number</code>	 */	public Fraction multiply(final long number) {		return multiply(valueOf(number));	}	/**	 * Divides this <tt>Fraction</tt> by the <code>other</code> one, then	 * returns the result of that division.	 * 	 * @param other	 *            The <tt>Fraction</tt> to divide this one by.	 * @return the result of the division of this <tt>Fraction</tt> by the	 *         <code>other</code> one	 */	public Fraction divide(final Fraction other) {		return multiply(other.inverse());	}	/**	 * Divides this <tt>Fraction</tt> by the given <code>number</code>,	 * then returns the result of that division.	 * 	 * @param number	 *            The number to divide this <tt>Fraction</tt> by.	 * @return the result of the division of this <tt>Fraction</tt> by the	 *         given <code>number</code>	 */	public Fraction divide(final long number) {		return divide(valueOf(number));	}	/**	 * Returns the inverse (1/x) of this <tt>Fraction</tt>. More formally,	 * returns a <tt>Fraction</tt> whose numerator is this one's denominator	 * and whose denominator is this one's numerator. If the resulting	 * <tt>Fraction</tt>'s denominator would be negative, it is made positive	 * and the numerator is negated so that <code>getDenominator</code>'s	 * contract is satisfied.	 * 	 * @return the inverse (1/x) of this <tt>Fraction</tt>	 */	public Fraction inverse() {		return new Fraction(denominator, numerator);	}	/**	 * Returns the negation (-x) of this <tt>Fraction</tt>. More formally,	 * returns a <tt>Fraction</tt> whose numerator is minus this one's	 * numerator and whose denominator is equal to this one's denominator.	 * 	 * @return the negation (-x) of this <tt>Fraction</tt>	 */	public Fraction negate() {		return new Fraction(-numerator, denominator);	}	/**	 * Returns the value held by this <tt>Fraction</tt>, as a	 * <code>double</code> value.	 * 	 * @return the value held by this <tt>Fraction</tt>, as a	 *         <code>double</code> value	 */	public double doubleValue() {		return (double) numerator / denominator;	}	/**	 * Returns the value held by this <tt>Fraction</tt>, as a	 * <code>float</code> value.	 * 	 * @return the value held by this <tt>Fraction</tt>, as a	 *         <code>float</code> value	 */	public float floatValue() {		return (float) doubleValue();	}	/**	 * Returns the value held by this <tt>Fraction</tt>, as if by	 * <blockquote><code>	 *   Long.toString(getNumerator()) + "/" + Long.toString(getDenominator())	 * </code></blockquote>	 */	@Override	public String toString() {		return Long.toString(numerator) + "/" + Long.toString(denominator);	}	/**	 * Reduces this <tt>Fraction</tt> and returns its reduced representation.	 * 	 * @return the result of the reduction of this <tt>Fraction</tt>	 */	public Fraction reduce() {		// Edge case: Denominator == 0? If so, return this		// Shortcut: Denominator == 1? If so, return this		if (denominator <= 1)			return this;		// Otherwise, find what divides both the numerator and the denominator		final long divisor = greatestCommonDivisor(numerator, denominator);		return new Fraction(numerator / divisor, denominator / divisor);	}	@Override	public int hashCode() {		final int PRIME = 31;		int result = 1;		final Fraction reduced = reduce();		result = PRIME * result				+ (int) (reduced.denominator ^ (reduced.denominator >>> 32));		result = PRIME * result				+ (int) (reduced.numerator ^ (reduced.numerator >>> 32));		return result;	}	/**	 * Determines whether this <tt>Fraction</tt> and the given <tt>Object</tt>	 * are equal; that is, that they	 * <ul>	 * <li>represent the same <tt>Object</tt>, or	 * <li>represent fractions with equal numerators and denominators, or	 * <li>represent fractions which, when reduced, represent fractions with	 * equal numerators and denominators.	 * </ul>	 */	@Override	public boolean equals(final Object obj) {		if (this == obj)			return true;		if (obj == null)			return false;		if (!(obj instanceof Fraction))			return false;		final Fraction other = (Fraction) obj;		if (numerator == other.numerator && denominator == other.denominator)			return true;		final Fraction reducedThis = reduce(), reducedOther = other.reduce();		if (reducedThis.numerator == reducedOther.numerator				&& reducedThis.denominator == reducedOther.denominator)			return true;		return false;	}	/**	 * Compares this <tt>Fraction</tt> with the specified <tt>Fraction</tt>	 * for order. Returns a negative integer, zero, or a positive integer as	 * this <tt>Fraction</tt> is less than, equal to, or greater than the	 * specified <tt>Fraction</tt>. Exceptions to this rule are as follows:	 * <ul>	 * <li>any <tt>Fraction</tt> that has 0 as its denominator will be	 * ordered before any other <tt>Fraction</tt> except another	 * <tt>Fraction</tt> that has 0 as its denominator;	 * <li> two <tt>Fraction</tt>s that have 0 as their denominators will be	 * ordered according to their numerators.	 * </ul>	 * 	 * @param o	 *            The <tt>Fraction</tt> to be compared with this one.	 * @return a negative integer, zero, or a positive integer as this	 *         <tt>Fraction</tt> is less than, equal to, or greater than the	 *         given <tt>Fraction</tt>	 */	public int compareTo(final Fraction o) {		if (denominator == 0) {			if (o.denominator == 0)				return (int) Math.signum(numerator - o.numerator);			else				return -1;		} else if (o.denominator == 0)			return 1;		else			return (int) Math.signum(doubleValue() - o.doubleValue());	}	/**	 * Calculates the greatest common divisor of the two given numbers using	 * Euclid's algorithm.	 * 	 * @param a	 *            The first number.	 * @param b	 *            The second number.	 * @return the greatest common divisor of the two given numbers	 */	private static long greatestCommonDivisor(final long a, final long b) {		if (b == 0L)			return a;		else			return greatestCommonDivisor(b, a % b);	}	public static void main(final String[] args) {		Fraction c, d, x; // Fraction Objects		c = new Fraction(5, 8);		d = new Fraction(4, 10);		x = new Fraction(); // create a fraction for the number 0		System.out.println(c);		System.out.println(d);		System.out.println(x);		x = x.add(c).add(d);		System.out.println(x);		System.out.println(x.doubleValue());		x = new Fraction(1); // create a fraction for the number 1		x = x.multiply(c).multiply(d);		System.out.println(x);		System.out.println(x.doubleValue());		x = new Fraction(6, 0);		System.out.println(x.doubleValue());	}}