package net.cynthia; /** * An immutable class containing a fraction. Operations in this class return a * new Fraction containing their result; they do not modify any * original Fraction. *
* Operations supported by objects of this class are: *
numerator
* and a denominator of 1.
*
* @param numerator
* The numerator of the newly created Fraction.
*/
public Fraction(final long numerator) {
this.numerator = numerator;
denominator = 1L;
}
/**
* Constructs a Fraction having the given numerator
* and denominator.
*
* @param numerator
* The numerator of the newly created Fraction.
* @param denominator
* The denominator of the newly created Fraction.
*/
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 Fractions 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 Fraction whose numerator is the given
* number and whose denominator is 1. Calling this method may
* be more efficient than creating Fractions on demand, since
* frequently-used values may be cached.
*
* @param number
* The number to use as the returned Fraction's
* numerator.
* @return a Fraction whose numerator is the given
* number 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 Fraction. The numerator is the
* integer above the division bar in a fraction when written out.
*
* @return the numerator of this Fraction
*/
public long getNumerator() {
return numerator;
}
/**
* Returns the denominator of this Fraction. 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 Fraction
*/
public long getDenominator() {
return denominator;
}
/**
* Adds this Fraction and the other one together,
* then returns the result of that addition.
*
* @param other
* The Fraction to add to this one.
* @return the result of the addition of this Fraction and the
* other 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 Fraction and the given number
* together, then returns the result of that addition.
*
* @param number
* The number to add to this Fraction.
* @return the result of the addition of this Fraction and the
* given number
*/
public Fraction add(final long number) {
return add(valueOf(number));
}
/**
* Subtracts the other Fraction from this one,
* then returns the result of that subtraction.
*
* @param other
* The Fraction to subtract from this one.
* @return the result of the subtraction of the
* other Fraction from this one
*/
public Fraction subtract(final Fraction other) {
return add(other.negate());
}
/**
* Subtracts the given number from this Fraction,
* then returns the result of that subtraction.
*
* @param number
* The number to subtract from this Fraction.
* @return the result of the subtraction of the given number
* from this Fraction
*/
public Fraction subtract(final long number) {
return subtract(valueOf(number));
}
/**
* Multiplies this Fraction by the other one, then
* returns the result of that multiplication.
*
* @param other
* The Fraction to multiply this one by.
* @return the result of the multiplication of this Fraction by
* the other one
*/
public Fraction multiply(final Fraction other) {
return new Fraction(numerator * other.numerator, denominator
* other.denominator);
}
/**
* Multiplies this Fraction by the given number,
* then returns the result of that multiplication.
*
* @param number
* The number to multiply this Fraction by.
* @return the result of the multiplication of this Fraction by
* the given number
*/
public Fraction multiply(final long number) {
return multiply(valueOf(number));
}
/**
* Divides this Fraction by the other one, then
* returns the result of that division.
*
* @param other
* The Fraction to divide this one by.
* @return the result of the division of this Fraction by the
* other one
*/
public Fraction divide(final Fraction other) {
return multiply(other.inverse());
}
/**
* Divides this Fraction by the given number,
* then returns the result of that division.
*
* @param number
* The number to divide this Fraction by.
* @return the result of the division of this Fraction by the
* given number
*/
public Fraction divide(final long number) {
return divide(valueOf(number));
}
/**
* Returns the inverse (1/x) of this Fraction. More formally,
* returns a Fraction whose numerator is this one's denominator
* and whose denominator is this one's numerator. If the resulting
* Fraction's denominator would be negative, it is made positive
* and the numerator is negated so that getDenominator's
* contract is satisfied.
*
* @return the inverse (1/x) of this Fraction
*/
public Fraction inverse() {
return new Fraction(denominator, numerator);
}
/**
* Returns the negation (-x) of this Fraction. More formally,
* returns a Fraction whose numerator is minus this one's
* numerator and whose denominator is equal to this one's denominator.
*
* @return the negation (-x) of this Fraction
*/
public Fraction negate() {
return new Fraction(-numerator, denominator);
}
/**
* Returns the value held by this Fraction, as a
* double value.
*
* @return the value held by this Fraction, as a
* double value
*/
public double doubleValue() {
return (double) numerator / denominator;
}
/**
* Returns the value held by this Fraction, as a
* float value.
*
* @return the value held by this Fraction, as a
* float value
*/
public float floatValue() {
return (float) doubleValue();
}
/**
* Returns the value held by this Fraction, as if by
*
* Long.toString(getNumerator()) + "/" + Long.toString(getDenominator())
*
*/
@Override
public String toString() {
return Long.toString(numerator) + "/" + Long.toString(denominator);
}
/**
* Reduces this Fraction and returns its reduced representation.
*
* @return the result of the reduction of this Fraction
*/
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 Fraction and the given Object
* are equal; that is, that they
*