Fields Summary |
---|
public static final Rational | NaNConstant for the Not-a-Number (NaN) value of the {@code Rational} type.
A {@code NaN} value is considered to be equal to itself (that is {@code NaN.equals(NaN)}
will return {@code true}; it is always greater than any non-{@code NaN} value (that is
{@code NaN.compareTo(notNaN)} will return a number greater than {@code 0}).
Equivalent to constructing a new rational with both the numerator and denominator
equal to {@code 0}. |
public static final Rational | POSITIVE_INFINITYConstant for the positive infinity value of the {@code Rational} type.
Equivalent to constructing a new rational with a positive numerator and a denominator
equal to {@code 0}. |
public static final Rational | NEGATIVE_INFINITYConstant for the negative infinity value of the {@code Rational} type.
Equivalent to constructing a new rational with a negative numerator and a denominator
equal to {@code 0}. |
public static final Rational | ZEROConstant for the zero value of the {@code Rational} type.
Equivalent to constructing a new rational with a numerator equal to {@code 0} and
any non-zero denominator. |
private static final long | serialVersionUIDUnique version number per class to be compliant with {@link java.io.Serializable}.
Increment each time the fields change in any way. |
private final int | mNumerator |
private final int | mDenominator |
Methods Summary |
---|
public int | compareTo(android.util.Rational another)Compare this rational to the specified rational to determine their natural order.
{@link #NaN} is considered to be equal to itself and greater than all other
{@code Rational} values. Otherwise, if the objects are not {@link #equals equal}, then
the following rules apply:
- Positive infinity is greater than any other finite number (or negative infinity)
- Negative infinity is less than any other finite number (or positive infinity)
- The finite number represented by this rational is checked numerically
against the other finite number by converting both rationals to a common denominator multiple
and comparing their numerators.
checkNotNull(another, "another must not be null");
if (equals(another)) {
return 0;
} else if (isNaN()) { // NaN is greater than the other non-NaN value
return 1;
} else if (another.isNaN()) { // the other NaN is greater than this non-NaN value
return -1;
} else if (isPosInf() || another.isNegInf()) {
return 1; // positive infinity is greater than any non-NaN/non-posInf value
} else if (isNegInf() || another.isPosInf()) {
return -1; // negative infinity is less than any non-NaN/non-negInf value
}
// else both this and another are finite numbers
// make the denominators the same, then compare numerators
long thisNumerator = ((long)mNumerator) * another.mDenominator; // long to avoid overflow
long otherNumerator = ((long)another.mNumerator) * mDenominator; // long to avoid overflow
// avoid underflow from subtraction by doing comparisons
if (thisNumerator < otherNumerator) {
return -1;
} else if (thisNumerator > otherNumerator) {
return 1;
} else {
// This should be covered by #equals, but have this code path just in case
return 0;
}
|
public double | doubleValue()Returns the value of the specified number as a {@code double}.
The {@code double} is calculated by converting both the numerator and denominator
to a {@code double}; then returning the result of dividing the numerator by the
denominator.
double num = mNumerator;
double den = mDenominator;
return num / den;
|
public boolean | equals(java.lang.Object obj)Compare this Rational to another object and see if they are equal.
A Rational object can only be equal to another Rational object (comparing against any
other type will return {@code false}).
A Rational object is considered equal to another Rational object if and only if one of
the following holds:
- Both are {@code NaN}
- Both are infinities of the same sign
- Both have the same numerator and denominator in their reduced form
A reduced form of a Rational is calculated by dividing both the numerator and the
denominator by their greatest common divisor.
{@code
(new Rational(1, 2)).equals(new Rational(1, 2)) == true // trivially true
(new Rational(2, 3)).equals(new Rational(1, 2)) == false // trivially false
(new Rational(1, 2)).equals(new Rational(2, 4)) == true // true after reduction
(new Rational(0, 0)).equals(new Rational(0, 0)) == true // NaN.equals(NaN)
(new Rational(1, 0)).equals(new Rational(5, 0)) == true // both are +infinity
(new Rational(1, 0)).equals(new Rational(-1, 0)) == false // +infinity != -infinity
}
return obj instanceof Rational && equals((Rational) obj);
|
private boolean | equals(android.util.Rational other)
return (mNumerator == other.mNumerator && mDenominator == other.mDenominator);
|
public float | floatValue()Returns the value of the specified number as a {@code float}.
The {@code float} is calculated by converting both the numerator and denominator
to a {@code float}; then returning the result of dividing the numerator by the
denominator.
float num = mNumerator;
float den = mDenominator;
return num / den;
|
public static int | gcd(int numerator, int denominator)Calculates the greatest common divisor using Euclid's algorithm.
Visible for testing only.
/*
* Non-recursive implementation of Euclid's algorithm:
*
* gcd(a, 0) := a
* gcd(a, b) := gcd(b, a mod b)
*
*/
int a = numerator;
int b = denominator;
while (b != 0) {
int oldB = b;
b = a % b;
a = oldB;
}
return Math.abs(a);
|
public int | getDenominator()Gets the denominator of the rational
The denominator may return {@code 0}, in which case the rational may represent
positive infinity (if the numerator was positive), negative infinity (if the numerator
was negative), or {@code NaN} (if the numerator was {@code 0}).
The denominator will always return {@code 1} if the numerator is {@code 0}.
return mDenominator;
|
public int | getNumerator()Gets the numerator of the rational.
The numerator will always return {@code 1} if this rational represents
infinity (that is, the denominator is {@code 0}).
return mNumerator;
|
public int | hashCode(){@inheritDoc}
// Bias the hash code for the first (2^16) values for both numerator and denominator
int numeratorFlipped = mNumerator << 16 | mNumerator >>> 16;
return mDenominator ^ numeratorFlipped;
|
public int | intValue()Returns the value of the specified number as a {@code int}.
{@link #isInfinite Finite} rationals are converted to an {@code int} value
by dividing the numerator by the denominator; conversion for non-finite values happens
identically to casting a floating point value to an {@code int}, in particular:
- Positive infinity saturates to the largest maximum integer
{@link Integer#MAX_VALUE}
- Negative infinity saturates to the smallest maximum integer
{@link Integer#MIN_VALUE}
- Not-A-Number (NaN) returns {@code 0}.
// Mimic float to int conversion rules from JLS 5.1.3
if (isPosInf()) {
return Integer.MAX_VALUE;
} else if (isNegInf()) {
return Integer.MIN_VALUE;
} else if (isNaN()) {
return 0;
} else { // finite
return mNumerator / mDenominator;
}
|
private static java.lang.NumberFormatException | invalidRational(java.lang.String s)
throw new NumberFormatException("Invalid Rational: \"" + s + "\"");
|
public boolean | isFinite()Indicates whether this rational represents a finite value.
A finite value occurs when the denominator is not {@code 0}; in other words
the rational is neither infinity or {@code NaN}.
return mDenominator != 0;
|
public boolean | isInfinite()Indicates whether this rational represents an infinite value.
An infinite value occurs when the denominator is {@code 0} (but the numerator is not).
return mNumerator != 0 && mDenominator == 0;
|
public boolean | isNaN()Indicates whether this rational is a Not-a-Number (NaN) value.
A {@code NaN} value occurs when both the numerator and the denominator are {@code 0}.
return mDenominator == 0 && mNumerator == 0;
|
private boolean | isNegInf()
return mDenominator == 0 && mNumerator < 0;
|
private boolean | isPosInf()
return mDenominator == 0 && mNumerator > 0;
|
public boolean | isZero()Indicates whether this rational represents a zero value.
A zero value is a {@link #isFinite finite} rational with a numerator of {@code 0}.
return isFinite() && mNumerator == 0;
|
public long | longValue()Returns the value of the specified number as a {@code long}.
{@link #isInfinite Finite} rationals are converted to an {@code long} value
by dividing the numerator by the denominator; conversion for non-finite values happens
identically to casting a floating point value to a {@code long}, in particular:
- Positive infinity saturates to the largest maximum long
{@link Long#MAX_VALUE}
- Negative infinity saturates to the smallest maximum long
{@link Long#MIN_VALUE}
- Not-A-Number (NaN) returns {@code 0}.
// Mimic float to long conversion rules from JLS 5.1.3
if (isPosInf()) {
return Long.MAX_VALUE;
} else if (isNegInf()) {
return Long.MIN_VALUE;
} else if (isNaN()) {
return 0;
} else { // finite
return mNumerator / mDenominator;
}
|
public static android.util.Rational | parseRational(java.lang.String string)Parses the specified string as a rational value.
The ASCII characters {@code \}{@code u003a} (':') and
{@code \}{@code u002f} ('/') are recognized as separators between
the numerator and denumerator.
For any {@code Rational r}: {@code Rational.parseRational(r.toString()).equals(r)}.
However, the method also handles rational numbers expressed in the
following forms:
"num{@code /}den" or
"num{@code :}den" {@code => new Rational(num, den);},
where num and den are string integers potentially
containing a sign, such as "-10", "+7" or "5".
{@code
Rational.parseRational("3:+6").equals(new Rational(1, 2)) == true
Rational.parseRational("-3/-6").equals(new Rational(1, 2)) == true
Rational.parseRational("4.56") => throws NumberFormatException
}
checkNotNull(string, "string must not be null");
if (string.equals("NaN")) {
return NaN;
} else if (string.equals("Infinity")) {
return POSITIVE_INFINITY;
} else if (string.equals("-Infinity")) {
return NEGATIVE_INFINITY;
}
int sep_ix = string.indexOf(':");
if (sep_ix < 0) {
sep_ix = string.indexOf('/");
}
if (sep_ix < 0) {
throw invalidRational(string);
}
try {
return new Rational(Integer.parseInt(string.substring(0, sep_ix)),
Integer.parseInt(string.substring(sep_ix + 1)));
} catch (NumberFormatException e) {
throw invalidRational(string);
}
|
private void | readObject(java.io.ObjectInputStream in)writeObject with default serialized form - guards against
deserializing non-reduced forms of the rational.
in.defaultReadObject();
/*
* Guard against trying to deserialize illegal values (in this case, ones
* that don't have a standard reduced form).
*
* - Non-finite values must be one of [0, 1], [0, 0], [0, 1], [0, -1]
* - Finite values must always have their greatest common divisor as 1
*/
if (mNumerator == 0) { // either zero or NaN
if (mDenominator == 1 || mDenominator == 0) {
return;
}
throw new InvalidObjectException(
"Rational must be deserialized from a reduced form for zero values");
} else if (mDenominator == 0) { // either positive or negative infinity
if (mNumerator == 1 || mNumerator == -1) {
return;
}
throw new InvalidObjectException(
"Rational must be deserialized from a reduced form for infinity values");
} else { // finite value
if (gcd(mNumerator, mDenominator) > 1) {
throw new InvalidObjectException(
"Rational must be deserialized from a reduced form for finite values");
}
}
|
public short | shortValue()Returns the value of the specified number as a {@code short}.
{@link #isInfinite Finite} rationals are converted to a {@code short} value
identically to {@link #intValue}; the {@code int} result is then truncated to a
{@code short} before returning the value.
return (short) intValue();
|
public float | toFloat()Convert to a floating point representation.
// TODO: remove this duplicate function (used in CTS and the shim)
return floatValue();
|
public java.lang.String | toString()Return a string representation of this rational, e.g. {@code "1/2"}.
The following rules of conversion apply:
- {@code NaN} values will return {@code "NaN"}
- Positive infinity values will return {@code "Infinity"}
- Negative infinity values will return {@code "-Infinity"}
- All other values will return {@code "numerator/denominator"} where {@code numerator}
and {@code denominator} are substituted with the appropriate numerator and denominator
values.
if (isNaN()) {
return "NaN";
} else if (isPosInf()) {
return "Infinity";
} else if (isNegInf()) {
return "-Infinity";
} else {
return mNumerator + "/" + mDenominator;
}
|