package tim.prune.jpeg.drew;
/**
* Immutable class for holding a rational number without loss of precision.
* Based on Drew Noakes' Metadata extractor at https://drewnoakes.com
*/
public class Rational
{
/** Holds the numerator */
private final long _numerator;
/** Holds the denominator */
private final long _denominator;
/**
* Creates a new (immutable) instance of Rational.
*/
public Rational(long numerator, long denominator)
{
_numerator = numerator;
_denominator = denominator;
}
/**
* @return the value of the specified number as a double
.
* This may involve rounding.
*/
public double doubleValue()
{
if (_denominator == 0L) return 0.0;
return (double)_numerator / (double)_denominator;
}
/**
* Returns the value of the specified number as an int
.
*/
public final int intValue()
{
return (int) longValue();
}
/**
* Returns the value of the specified number as a long
.
* This may involve rounding or truncation.
* If the denominator is 0, returns 0 to avoid dividing by 0.
*/
public final long longValue()
{
if (_denominator == 0L) return 0L;
return _numerator / _denominator;
}
/** Returns the denominator */
public final long getDenominator()
{
return _denominator;
}
/** Returns the numerator */
public final long getNumerator()
{
return _numerator;
}
/**
* @return the value of the specified number as a positive double
.
* Prevents interpretation of 32 bit numbers as negative, and forces a positive answer.
* Needed?
*/
public double convertToPositiveValue()
{
if (_denominator == 0L) return 0.0;
double numeratorDbl = _numerator;
double denomDbl = _denominator;
if (_numerator >= 0L) {
// Numerator is positive (but maybe denominator isn't?)
return numeratorDbl / denomDbl;
}
// Add 2^32 to negative doubles to make them positive
final double correction = Math.pow(2.0, 32);
numeratorDbl += correction;
if (_denominator < 0L) {
denomDbl += correction;
}
return numeratorDbl / denomDbl;
}
/**
* Returns a string representation of the object of form numerator/denominator
.
*/
@Override
public String toString()
{
return "" + _numerator + "/" + _denominator;
}
/**
* Compares two {@link Rational} instances, returning true if they are mathematically
* equivalent.
*
* @param obj the {@link Rational} to compare this instance to.
* @return true if instances are mathematically equivalent, otherwise false. Will also
* give false if obj
is not an instance of {@link Rational}.
*/
@Override
public boolean equals( Object obj)
{
if (obj==null || !(obj instanceof Rational))
return false;
Rational that = (Rational) obj;
return this.doubleValue() == that.doubleValue();
}
}