You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ah...@apache.org on 2020/04/07 12:43:35 UTC
[commons-numbers] 03/09: Fraction/BigFraction to use same method
order:
This is an automated email from the ASF dual-hosted git repository.
aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-numbers.git
commit 7a94e4afb853c4e32b19a6ef0053937bf4bd7c2e
Author: aherbert <ah...@apache.org>
AuthorDate: Tue Apr 7 11:00:22 2020 +0100
Fraction/BigFraction to use same method order:
private constructors
factory constructors, including parse(String)
Properties:
zero(), one()
numerator(), denominator()
Computed properties:
signum
Conversions:
abs, negate, reciprocal
primitive values (double/float/int/longValue,etc)
Math:
Arithmetic
add,subtract,multiply,divide
Power functions
Standard object stuff:
toString(), compareTo, equals(), hashCode()
---
.../commons/numbers/fraction/BigFraction.java | 1153 ++++++++++----------
.../apache/commons/numbers/fraction/Fraction.java | 414 +++----
2 files changed, 786 insertions(+), 781 deletions(-)
diff --git a/commons-numbers-fraction/src/main/java/org/apache/commons/numbers/fraction/BigFraction.java b/commons-numbers-fraction/src/main/java/org/apache/commons/numbers/fraction/BigFraction.java
index a62e0d7..9a969c9 100644
--- a/commons-numbers-fraction/src/main/java/org/apache/commons/numbers/fraction/BigFraction.java
+++ b/commons-numbers-fraction/src/main/java/org/apache/commons/numbers/fraction/BigFraction.java
@@ -310,16 +310,13 @@ public final class BigFraction
}
/**
- * Create a fraction given the numerator and denominator.
- * The fraction is reduced to lowest terms.
+ * Create a fraction given the numerator. The denominator is {@code 1}.
*
* @param num the numerator.
- * @param den the denominator.
* @return a new instance.
- * @throws ArithmeticException if {@code den} is zero.
*/
- public static BigFraction of(final int num, final int den) {
- return new BigFraction(BigInteger.valueOf(num), BigInteger.valueOf(den));
+ public static BigFraction of(final long num) {
+ return new BigFraction(BigInteger.valueOf(num), BigInteger.ONE);
}
/**
@@ -327,9 +324,10 @@ public final class BigFraction
*
* @param num the numerator.
* @return a new instance.
+ * @throws NullPointerException if numerator is null.
*/
- public static BigFraction of(final long num) {
- return new BigFraction(BigInteger.valueOf(num), BigInteger.ONE);
+ public static BigFraction of(final BigInteger num) {
+ return new BigFraction(num, BigInteger.ONE);
}
/**
@@ -341,19 +339,21 @@ public final class BigFraction
* @return a new instance.
* @throws ArithmeticException if {@code den} is zero.
*/
- public static BigFraction of(final long num, final long den) {
+ public static BigFraction of(final int num, final int den) {
return new BigFraction(BigInteger.valueOf(num), BigInteger.valueOf(den));
}
/**
- * Create a fraction given the numerator. The denominator is {@code 1}.
+ * Create a fraction given the numerator and denominator.
+ * The fraction is reduced to lowest terms.
*
* @param num the numerator.
+ * @param den the denominator.
* @return a new instance.
- * @throws NullPointerException if numerator is null.
+ * @throws ArithmeticException if {@code den} is zero.
*/
- public static BigFraction of(final BigInteger num) {
- return new BigFraction(num, BigInteger.ONE);
+ public static BigFraction of(final long num, final long den) {
+ return new BigFraction(BigInteger.valueOf(num), BigInteger.valueOf(den));
}
/**
@@ -366,10 +366,117 @@ public final class BigFraction
* @throws ArithmeticException if the denominator is zero.
* @throws NullPointerException if numerator or denominator are null.
*/
- public static BigFraction of(BigInteger num, BigInteger den) {
+ public static BigFraction of(final BigInteger num, final BigInteger den) {
return new BigFraction(num, den);
}
+
+ /**
+ * Parses a string that would be produced by {@link #toString()}
+ * and instantiates the corresponding object.
+ *
+ * @param s String representation.
+ * @return an instance.
+ * @throws NumberFormatException if the string does not conform
+ * to the specification.
+ */
+ public static BigFraction parse(String s) {
+ s = s.replace(",", "");
+ final int slashLoc = s.indexOf('/');
+ // if no slash, parse as single number
+ if (slashLoc == -1) {
+ return BigFraction.of(new BigInteger(s.trim()));
+ }
+ final BigInteger num = new BigInteger(
+ s.substring(0, slashLoc).trim());
+ final BigInteger denom = new BigInteger(s.substring(slashLoc + 1).trim());
+ return of(num, denom);
+ }
+
+ @Override
+ public BigFraction zero() {
+ return ZERO;
+ }
+
+ @Override
+ public BigFraction one() {
+ return ONE;
+ }
+
+ /**
+ * Access the numerator as a {@code BigInteger}.
+ *
+ * @return the numerator as a {@code BigInteger}.
+ */
+ public BigInteger getNumerator() {
+ return numerator;
+ }
+
+ /**
+ * Access the numerator as an {@code int}.
+ *
+ * @return the numerator as an {@code int}.
+ */
+ public int getNumeratorAsInt() {
+ return numerator.intValue();
+ }
+
+ /**
+ * Access the numerator as a {@code long}.
+ *
+ * @return the numerator as a {@code long}.
+ */
+ public long getNumeratorAsLong() {
+ return numerator.longValue();
+ }
+
+ /**
+ * Access the denominator as a {@code BigInteger}.
+ *
+ * @return the denominator as a {@code BigInteger}.
+ */
+ public BigInteger getDenominator() {
+ return denominator;
+ }
+
+ /**
+ * Access the denominator as an {@code int}.
+ *
+ * @return the denominator as an {@code int}.
+ */
+ public int getDenominatorAsInt() {
+ return denominator.intValue();
+ }
+
+ /**
+ * Access the denominator as a {@code long}.
+ *
+ * @return the denominator as a {@code long}.
+ */
+ public long getDenominatorAsLong() {
+ return denominator.longValue();
+ }
+
+ /**
+ * Retrieves the sign of this fraction.
+ *
+ * @return -1 if the value is strictly negative, 1 if it is strictly
+ * positive, 0 if it is 0.
+ */
+ public int signum() {
+ final int numS = numerator.signum();
+ final int denS = denominator.signum();
+
+ if ((numS > 0 && denS > 0) ||
+ (numS < 0 && denS < 0)) {
+ return 1;
+ } else if (numS == 0) {
+ return 0;
+ } else {
+ return -1;
+ }
+ }
+
/**
* Returns the absolute value of this fraction.
*
@@ -382,82 +489,72 @@ public final class BigFraction
}
/**
- * Adds the value of this fraction to the passed {@link BigInteger},
- * returning the result in reduced form.
+ * Return the additive inverse of this fraction, returning the result in
+ * reduced form.
*
- * @param bg
- * the {@link BigInteger} to add, must'nt be {@code null}.
- * @return a {@code BigFraction} instance with the resulting values.
+ * @return the negation of this fraction.
*/
- public BigFraction add(final BigInteger bg) {
- if (numerator.signum() == 0) {
- return of(bg);
- }
- if (bg.signum() == 0) {
- return this;
- }
-
- return new BigFraction(numerator.add(denominator.multiply(bg)), denominator);
+ @Override
+ public BigFraction negate() {
+ return new BigFraction(numerator.negate(), denominator);
}
/**
- * Adds the value of this fraction to the passed {@code integer}, returning
- * the result in reduced form.
+ * Return the multiplicative inverse of this fraction.
*
- * @param i
- * the {@code integer} to add.
- * @return a {@code BigFraction} instance with the resulting values.
+ * @return the reciprocal fraction.
*/
- public BigFraction add(final int i) {
- return add(BigInteger.valueOf(i));
+ @Override
+ public BigFraction reciprocal() {
+ return new BigFraction(denominator, numerator);
}
/**
- * Adds the value of this fraction to the passed {@code long}, returning
- * the result in reduced form.
+ * Gets the fraction as a {@code double}. This calculates the fraction as
+ * the numerator divided by denominator.
*
- * @param l
- * the {@code long} to add.
- * @return a {@code BigFraction} instance with the resulting values.
+ * @return the fraction as a {@code double}
+ * @see java.lang.Number#doubleValue()
*/
- public BigFraction add(final long l) {
- return add(BigInteger.valueOf(l));
+ @Override
+ public double doubleValue() {
+ return Double.longBitsToDouble(toFloatingPointBits(11, 52));
}
/**
- * Adds the value of this fraction to another, returning the result in
- * reduced form.
+ * Retrieves the {@code float} value closest to this fraction.
+ * This calculates the fraction as numerator divided by denominator.
*
- * @param fraction
- * the {@link BigFraction} to add, must not be {@code null}.
- * @return a {@link BigFraction} instance with the resulting values.
+ * @return the fraction as a {@code float}.
+ * @see java.lang.Number#floatValue()
*/
@Override
- public BigFraction add(final BigFraction fraction) {
- if (fraction.numerator.signum() == 0) {
- return this;
- }
- if (numerator.signum() == 0) {
- return fraction;
- }
-
- final BigInteger num;
- final BigInteger den;
-
- if (denominator.equals(fraction.denominator)) {
- num = numerator.add(fraction.numerator);
- den = denominator;
- } else {
- num = (numerator.multiply(fraction.denominator)).add((fraction.numerator).multiply(denominator));
- den = denominator.multiply(fraction.denominator);
- }
-
- if (num.signum() == 0) {
- return ZERO;
- }
+ public float floatValue() {
+ return Float.intBitsToFloat((int) toFloatingPointBits(8, 23));
+ }
- return new BigFraction(num, den);
+ /**
+ * Gets the fraction as an {@code int}. This returns the whole number part
+ * of the fraction.
+ *
+ * @return the whole number fraction part.
+ * @see java.lang.Number#intValue()
+ */
+ @Override
+ public int intValue() {
+ return numerator.divide(denominator).intValue();
+ }
+ /**
+ * Gets the fraction as a {@code long}. This returns the whole number part
+ * of the fraction.
+ *
+ * @return the whole number fraction part.
+ * @see java.lang.Number#longValue()
+ */
+ @Override
+ public long longValue() {
+ return numerator.divide(denominator).longValue();
}
/**
@@ -506,47 +603,213 @@ public final class BigFraction
}
/**
- * Compares this object to another based on size.
- *
- * @param other Object to compare to, must not be {@code null}.
- * @return -1 if this is less than {@code object}, +1 if this is greater
- * than {@code object}, 0 if they are equal.
+ * Adds the value of this fraction to the passed {@code integer}, returning
+ * the result in reduced form.
*
- * @see Comparable#compareTo(Object)
+ * @param i
+ * the {@code integer} to add.
+ * @return a {@code BigFraction} instance with the resulting values.
*/
- @Override
- public int compareTo(final BigFraction other) {
- final int lhsSigNum = signum();
- final int rhsSigNum = other.signum();
-
- if (lhsSigNum != rhsSigNum) {
- return (lhsSigNum > rhsSigNum) ? 1 : -1;
- }
- if (lhsSigNum == 0) {
- return 0;
- }
+ public BigFraction add(final int i) {
+ return add(BigInteger.valueOf(i));
+ }
- final BigInteger nOd = numerator.multiply(other.denominator);
- final BigInteger dOn = denominator.multiply(other.numerator);
- return nOd.compareTo(dOn);
+ /**
+ * Adds the value of this fraction to the passed {@code long}, returning
+ * the result in reduced form.
+ *
+ * @param l
+ * the {@code long} to add.
+ * @return a {@code BigFraction} instance with the resulting values.
+ */
+ public BigFraction add(final long l) {
+ return add(BigInteger.valueOf(l));
}
/**
- * Divide the value of this fraction by the passed {@code BigInteger},
- * ie {@code this * 1 / bg}, returning the result in reduced form.
+ * Adds the value of this fraction to the passed {@link BigInteger},
+ * returning the result in reduced form.
*
- * @param bg the {@code BigInteger} to divide by, must not be {@code null}
- * @return a {@link BigFraction} instance with the resulting values
- * @throws ArithmeticException if the value to divide by is zero
+ * @param bg
+ * the {@link BigInteger} to add, must'nt be {@code null}.
+ * @return a {@code BigFraction} instance with the resulting values.
*/
- public BigFraction divide(final BigInteger bg) {
+ public BigFraction add(final BigInteger bg) {
+ if (numerator.signum() == 0) {
+ return of(bg);
+ }
if (bg.signum() == 0) {
- throw new FractionException(FractionException.ERROR_ZERO_DENOMINATOR);
+ return this;
+ }
+
+ return new BigFraction(numerator.add(denominator.multiply(bg)), denominator);
+ }
+
+ /**
+ * Adds the value of this fraction to another, returning the result in
+ * reduced form.
+ *
+ * @param fraction
+ * the {@link BigFraction} to add, must not be {@code null}.
+ * @return a {@link BigFraction} instance with the resulting values.
+ */
+ @Override
+ public BigFraction add(final BigFraction fraction) {
+ if (fraction.numerator.signum() == 0) {
+ return this;
}
if (numerator.signum() == 0) {
+ return fraction;
+ }
+
+ final BigInteger num;
+ final BigInteger den;
+
+ if (denominator.equals(fraction.denominator)) {
+ num = numerator.add(fraction.numerator);
+ den = denominator;
+ } else {
+ num = (numerator.multiply(fraction.denominator)).add((fraction.numerator).multiply(denominator));
+ den = denominator.multiply(fraction.denominator);
+ }
+
+ if (num.signum() == 0) {
return ZERO;
}
- return new BigFraction(numerator, denominator.multiply(bg));
+
+ return new BigFraction(num, den);
+ }
+
+ /**
+ * Subtracts the value of an {@code integer} from the value of this
+ * {@code BigFraction}, returning the result in reduced form.
+ *
+ * @param i the {@code integer} to subtract.
+ * @return a {@code BigFraction} instance with the resulting values.
+ */
+ public BigFraction subtract(final int i) {
+ return subtract(BigInteger.valueOf(i));
+ }
+
+ /**
+ * Subtracts the value of a {@code long} from the value of this
+ * {@code BigFraction}, returning the result in reduced form.
+ *
+ * @param l the {@code long} to subtract.
+ * @return a {@code BigFraction} instance with the resulting values.
+ */
+ public BigFraction subtract(final long l) {
+ return subtract(BigInteger.valueOf(l));
+ }
+
+ /**
+ * Subtracts the value of an {@link BigInteger} from the value of this
+ * {@code BigFraction}, returning the result in reduced form.
+ *
+ * @param bg the {@link BigInteger} to subtract, cannot be {@code null}.
+ * @return a {@code BigFraction} instance with the resulting values.
+ */
+ public BigFraction subtract(final BigInteger bg) {
+ if (bg.signum() == 0) {
+ return this;
+ }
+ if (numerator.signum() == 0) {
+ return of(bg.negate());
+ }
+
+ return new BigFraction(numerator.subtract(denominator.multiply(bg)), denominator);
+ }
+
+ /**
+ * Subtracts the value of another fraction from the value of this one,
+ * returning the result in reduced form.
+ *
+ * @param fraction {@link BigFraction} to subtract, must not be {@code null}.
+ * @return a {@link BigFraction} instance with the resulting values
+ */
+ @Override
+ public BigFraction subtract(final BigFraction fraction) {
+ if (fraction.numerator.signum() == 0) {
+ return this;
+ }
+ if (numerator.signum() == 0) {
+ return fraction.negate();
+ }
+
+ final BigInteger num;
+ final BigInteger den;
+ if (denominator.equals(fraction.denominator)) {
+ num = numerator.subtract(fraction.numerator);
+ den = denominator;
+ } else {
+ num = (numerator.multiply(fraction.denominator)).subtract((fraction.numerator).multiply(denominator));
+ den = denominator.multiply(fraction.denominator);
+ }
+ return new BigFraction(num, den);
+ }
+
+ /**
+ * Multiply the value of this fraction by the passed {@code int}, returning
+ * the result in reduced form.
+ *
+ * @param i
+ * the {@code int} to multiply by.
+ * @return a {@link BigFraction} instance with the resulting values.
+ */
+ @Override
+ public BigFraction multiply(final int i) {
+ if (i == 0 || numerator.signum() == 0) {
+ return ZERO;
+ }
+
+ return multiply(BigInteger.valueOf(i));
+ }
+
+ /**
+ * Multiply the value of this fraction by the passed {@code long},
+ * returning the result in reduced form.
+ *
+ * @param l
+ * the {@code long} to multiply by.
+ * @return a {@link BigFraction} instance with the resulting values.
+ */
+ public BigFraction multiply(final long l) {
+ if (l == 0 || numerator.signum() == 0) {
+ return ZERO;
+ }
+
+ return multiply(BigInteger.valueOf(l));
+ }
+
+ /**
+ * Multiplies the value of this fraction by the passed
+ * {@code BigInteger}, returning the result in reduced form.
+ *
+ * @param bg the {@code BigInteger} to multiply by.
+ * @return a {@code BigFraction} instance with the resulting values.
+ */
+ public BigFraction multiply(final BigInteger bg) {
+ if (numerator.signum() == 0 || bg.signum() == 0) {
+ return ZERO;
+ }
+ return new BigFraction(bg.multiply(numerator), denominator);
+ }
+
+ /**
+ * Multiplies the value of this fraction by another, returning the result in
+ * reduced form.
+ *
+ * @param fraction Fraction to multiply by, must not be {@code null}.
+ * @return a {@link BigFraction} instance with the resulting values.
+ */
+ @Override
+ public BigFraction multiply(final BigFraction fraction) {
+ if (numerator.signum() == 0 ||
+ fraction.numerator.signum() == 0) {
+ return ZERO;
+ }
+ return new BigFraction(numerator.multiply(fraction.numerator),
+ denominator.multiply(fraction.denominator));
}
/**
@@ -574,6 +837,24 @@ public final class BigFraction
}
/**
+ * Divide the value of this fraction by the passed {@code BigInteger},
+ * ie {@code this * 1 / bg}, returning the result in reduced form.
+ *
+ * @param bg the {@code BigInteger} to divide by, must not be {@code null}
+ * @return a {@link BigFraction} instance with the resulting values
+ * @throws ArithmeticException if the value to divide by is zero
+ */
+ public BigFraction divide(final BigInteger bg) {
+ if (bg.signum() == 0) {
+ throw new FractionException(FractionException.ERROR_ZERO_DENOMINATOR);
+ }
+ if (numerator.signum() == 0) {
+ return ZERO;
+ }
+ return new BigFraction(numerator, denominator.multiply(bg));
+ }
+
+ /**
* Divide the value of this fraction by another, returning the result in
* reduced form.
*
@@ -594,40 +875,205 @@ public final class BigFraction
}
/**
- * Calculates the sign bit, the biased exponent and the significand for a
- * binary floating-point representation of this {@code BigFraction}
- * according to the IEEE 754 standard, and encodes these values into a {@code long}
- * variable. The representative bits are arranged adjacent to each other and
- * placed at the low-order end of the returned {@code long} value, with the
- * least significant bits used for the significand, the next more
- * significant bits for the exponent, and next more significant bit for the
- * sign.
- *
- * <p>Warning: The arguments are not validated.
+ * Returns a {@code BigFraction} whose value is
+ * {@code (this<sup>exponent</sup>)}, returning the result in reduced form.
*
- * @param exponentLength the number of bits allowed for the exponent; must be
- * between 1 and 32 (inclusive), and must not be greater
- * than {@code 63 - significandLength}
- * @param significandLength the number of bits allowed for the significand
- * (excluding the implicit leading 1-bit in
- * normalized numbers, e.g. 52 for a double-precision
- * floating-point number); must be between 1 and
- * {@code 63 - exponentLength} (inclusive)
- * @return the bits of an IEEE 754 binary floating-point representation of
- * this fraction encoded in a {@code long}, as described above.
+ * @param exponent
+ * exponent to which this {@code BigFraction} is to be
+ * raised.
+ * @return \(\mathit{this}^{\mathit{exponent}}\).
*/
- private long toFloatingPointBits(int exponentLength, int significandLength) {
- // Assume the following conditions:
- //assert exponentLength >= 1;
- //assert exponentLength <= 32;
- //assert significandLength >= 1;
- //assert significandLength <= 63 - exponentLength;
-
+ @Override
+ public BigFraction pow(final int exponent) {
+ if (exponent == 0) {
+ return ONE;
+ }
if (numerator.signum() == 0) {
- return 0L;
+ return this;
}
- final long sign = (numerator.signum() * denominator.signum()) == -1 ? 1L : 0L;
+ if (exponent < 0) {
+ return new BigFraction(denominator.pow(-exponent), numerator.pow(-exponent));
+ }
+ return new BigFraction(numerator.pow(exponent), denominator.pow(exponent));
+ }
+
+ /**
+ * Returns a {@code BigFraction} whose value is
+ * \(\mathit{this}^{\mathit{exponent}}\), returning the result in reduced form.
+ *
+ * @param exponent
+ * exponent to which this {@code BigFraction} is to be raised.
+ * @return \(\mathit{this}^{\mathit{exponent}}\) as a {@code BigFraction}.
+ */
+ public BigFraction pow(final long exponent) {
+ if (exponent == 0) {
+ return ONE;
+ }
+ if (numerator.signum() == 0) {
+ return this;
+ }
+
+ if (exponent < 0) {
+ return new BigFraction(ArithmeticUtils.pow(denominator, -exponent),
+ ArithmeticUtils.pow(numerator, -exponent));
+ }
+ return new BigFraction(ArithmeticUtils.pow(numerator, exponent),
+ ArithmeticUtils.pow(denominator, exponent));
+ }
+
+ /**
+ * Returns a {@code BigFraction} whose value is
+ * \(\mathit{this}^{\mathit{exponent}}\), returning the result in reduced form.
+ *
+ * @param exponent
+ * exponent to which this {@code BigFraction} is to be raised.
+ * @return \(\mathit{this}^{\mathit{exponent}}\) as a {@code BigFraction}.
+ */
+ public BigFraction pow(final BigInteger exponent) {
+ if (exponent.signum() == 0) {
+ return ONE;
+ }
+ if (numerator.signum() == 0) {
+ return this;
+ }
+
+ if (exponent.signum() == -1) {
+ final BigInteger eNeg = exponent.negate();
+ return new BigFraction(ArithmeticUtils.pow(denominator, eNeg),
+ ArithmeticUtils.pow(numerator, eNeg));
+ }
+ return new BigFraction(ArithmeticUtils.pow(numerator, exponent),
+ ArithmeticUtils.pow(denominator, exponent));
+ }
+
+ /**
+ * Returns a {@code double} whose value is
+ * \(\mathit{this}^{\mathit{exponent}}\), returning the result in reduced form.
+ *
+ * @param exponent
+ * exponent to which this {@code BigFraction} is to be raised.
+ * @return \(\mathit{this}^{\mathit{exponent}}\).
+ */
+ public double pow(final double exponent) {
+ return Math.pow(numerator.doubleValue(), exponent) /
+ Math.pow(denominator.doubleValue(), exponent);
+ }
+
+ /**
+ * Returns the {@code String} representing this fraction.
+ * Uses:
+ * <ul>
+ * <li>{@code "0"} if {@code numerator} is zero.
+ * <li>{@code "numerator"} if {@code denominator} is one.
+ * <li>{@code "numerator / denominator"} for all other cases.
+ * </ul>
+ *
+ * @return a string representation of the fraction.
+ */
+ @Override
+ public String toString() {
+ final String str;
+ if (BigInteger.ONE.equals(denominator)) {
+ str = numerator.toString();
+ } else if (BigInteger.ZERO.equals(numerator)) {
+ str = "0";
+ } else {
+ str = numerator + " / " + denominator;
+ }
+ return str;
+ }
+
+ /**
+ * Compares this object to another based on size.
+ *
+ * @param other Object to compare to, must not be {@code null}.
+ * @return -1 if this is less than {@code object}, +1 if this is greater
+ * than {@code object}, 0 if they are equal.
+ *
+ * @see Comparable#compareTo(Object)
+ */
+ @Override
+ public int compareTo(final BigFraction other) {
+ final int lhsSigNum = signum();
+ final int rhsSigNum = other.signum();
+
+ if (lhsSigNum != rhsSigNum) {
+ return (lhsSigNum > rhsSigNum) ? 1 : -1;
+ }
+ if (lhsSigNum == 0) {
+ return 0;
+ }
+
+ final BigInteger nOd = numerator.multiply(other.denominator);
+ final BigInteger dOn = denominator.multiply(other.numerator);
+ return nOd.compareTo(dOn);
+ }
+
+ /**
+ * Test for the equality of two fractions. If the lowest term numerator and
+ * denominators are the same for both fractions, the two fractions are
+ * considered to be equal.
+ *
+ * @param other {@inheritDoc}
+ * @return {@inheritDoc}
+ */
+ @Override
+ public boolean equals(final Object other) {
+ if (this == other) {
+ return true;
+ } else if (other instanceof BigFraction) {
+ final BigFraction rhs = (BigFraction) other;
+
+ if (signum() == rhs.signum()) {
+ return numerator.abs().equals(rhs.numerator.abs()) &&
+ denominator.abs().equals(rhs.denominator.abs());
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return 37 * (37 * 17 + numerator.hashCode()) + denominator.hashCode();
+ }
+
+ /**
+ * Calculates the sign bit, the biased exponent and the significand for a
+ * binary floating-point representation of this {@code BigFraction}
+ * according to the IEEE 754 standard, and encodes these values into a {@code long}
+ * variable. The representative bits are arranged adjacent to each other and
+ * placed at the low-order end of the returned {@code long} value, with the
+ * least significant bits used for the significand, the next more
+ * significant bits for the exponent, and next more significant bit for the
+ * sign.
+ *
+ * <p>Warning: The arguments are not validated.
+ *
+ * @param exponentLength the number of bits allowed for the exponent; must be
+ * between 1 and 32 (inclusive), and must not be greater
+ * than {@code 63 - significandLength}
+ * @param significandLength the number of bits allowed for the significand
+ * (excluding the implicit leading 1-bit in
+ * normalized numbers, e.g. 52 for a double-precision
+ * floating-point number); must be between 1 and
+ * {@code 63 - exponentLength} (inclusive)
+ * @return the bits of an IEEE 754 binary floating-point representation of
+ * this fraction encoded in a {@code long}, as described above.
+ */
+ private long toFloatingPointBits(int exponentLength, int significandLength) {
+ // Assume the following conditions:
+ //assert exponentLength >= 1;
+ //assert exponentLength <= 32;
+ //assert significandLength >= 1;
+ //assert significandLength <= 63 - exponentLength;
+
+ if (numerator.signum() == 0) {
+ return 0L;
+ }
+
+ final long sign = (numerator.signum() * denominator.signum()) == -1 ? 1L : 0L;
final BigInteger positiveNumerator = numerator.abs();
final BigInteger positiveDenominator = denominator.abs();
@@ -757,18 +1203,6 @@ public final class BigFraction
}
/**
- * Gets the fraction as a {@code double}. This calculates the fraction as
- * the numerator divided by denominator.
- *
- * @return the fraction as a {@code double}
- * @see java.lang.Number#doubleValue()
- */
- @Override
- public double doubleValue() {
- return Double.longBitsToDouble(toFloatingPointBits(11, 52));
- }
-
- /**
* Rounds an integer to the specified power of two (i.e. the minimum number of
* low-order bits that must be zero) and performs a right-shift by this
* amount. The rounding mode applied is round to nearest, with ties rounding
@@ -798,445 +1232,4 @@ public final class BigFraction
return result;
}
-
- /**
- * Test for the equality of two fractions. If the lowest term numerator and
- * denominators are the same for both fractions, the two fractions are
- * considered to be equal.
- *
- * @param other
- * fraction to test for equality to this fraction, can be
- * {@code null}.
- * @return true if two fractions are equal, false if object is
- * {@code null}, not an instance of {@link BigFraction}, or not
- * equal to this fraction instance.
- * @see java.lang.Object#equals(java.lang.Object)
- */
- @Override
- public boolean equals(final Object other) {
- if (this == other) {
- return true;
- } else if (other instanceof BigFraction) {
- final BigFraction rhs = (BigFraction) other;
-
- if (signum() == rhs.signum()) {
- return numerator.abs().equals(rhs.numerator.abs()) &&
- denominator.abs().equals(rhs.denominator.abs());
- } else {
- return false;
- }
- }
-
- return false;
- }
-
- /**
- * Retrieves the {@code float} value closest to this fraction.
- * This calculates the fraction as numerator divided by denominator.
- *
- * @return the fraction as a {@code float}.
- * @see java.lang.Number#floatValue()
- */
- @Override
- public float floatValue() {
- return Float.intBitsToFloat((int) toFloatingPointBits(8, 23));
- }
-
- /**
- * Access the denominator as a {@code BigInteger}.
- *
- * @return the denominator as a {@code BigInteger}.
- */
- public BigInteger getDenominator() {
- return denominator;
- }
-
- /**
- * Access the denominator as an {@code int}.
- *
- * @return the denominator as an {@code int}.
- */
- public int getDenominatorAsInt() {
- return denominator.intValue();
- }
-
- /**
- * Access the denominator as a {@code long}.
- *
- * @return the denominator as a {@code long}.
- */
- public long getDenominatorAsLong() {
- return denominator.longValue();
- }
-
- /**
- * Access the numerator as a {@code BigInteger}.
- *
- * @return the numerator as a {@code BigInteger}.
- */
- public BigInteger getNumerator() {
- return numerator;
- }
-
- /**
- * Access the numerator as an {@code int}.
- *
- * @return the numerator as an {@code int}.
- */
- public int getNumeratorAsInt() {
- return numerator.intValue();
- }
-
- /**
- * Access the numerator as a {@code long}.
- *
- * @return the numerator as a {@code long}.
- */
- public long getNumeratorAsLong() {
- return numerator.longValue();
- }
-
- /** {@inheritDoc} */
- @Override
- public int hashCode() {
- return 37 * (37 * 17 + numerator.hashCode()) + denominator.hashCode();
- }
-
- /**
- * Gets the fraction as an {@code int}. This returns the whole number part
- * of the fraction.
- *
- * @return the whole number fraction part.
- * @see java.lang.Number#intValue()
- */
- @Override
- public int intValue() {
- return numerator.divide(denominator).intValue();
- }
-
- /**
- * Gets the fraction as a {@code long}. This returns the whole number part
- * of the fraction.
- *
- * @return the whole number fraction part.
- * @see java.lang.Number#longValue()
- */
- @Override
- public long longValue() {
- return numerator.divide(denominator).longValue();
- }
-
- /**
- * Multiplies the value of this fraction by the passed
- * {@code BigInteger}, returning the result in reduced form.
- *
- * @param bg the {@code BigInteger} to multiply by.
- * @return a {@code BigFraction} instance with the resulting values.
- */
- public BigFraction multiply(final BigInteger bg) {
- if (numerator.signum() == 0 || bg.signum() == 0) {
- return ZERO;
- }
- return new BigFraction(bg.multiply(numerator), denominator);
- }
-
- /**
- * Multiply the value of this fraction by the passed {@code int}, returning
- * the result in reduced form.
- *
- * @param i
- * the {@code int} to multiply by.
- * @return a {@link BigFraction} instance with the resulting values.
- */
- @Override
- public BigFraction multiply(final int i) {
- if (i == 0 || numerator.signum() == 0) {
- return ZERO;
- }
-
- return multiply(BigInteger.valueOf(i));
- }
-
- /**
- * Multiply the value of this fraction by the passed {@code long},
- * returning the result in reduced form.
- *
- * @param l
- * the {@code long} to multiply by.
- * @return a {@link BigFraction} instance with the resulting values.
- */
- public BigFraction multiply(final long l) {
- if (l == 0 || numerator.signum() == 0) {
- return ZERO;
- }
-
- return multiply(BigInteger.valueOf(l));
- }
-
- /**
- * Multiplies the value of this fraction by another, returning the result in
- * reduced form.
- *
- * @param fraction Fraction to multiply by, must not be {@code null}.
- * @return a {@link BigFraction} instance with the resulting values.
- */
- @Override
- public BigFraction multiply(final BigFraction fraction) {
- if (numerator.signum() == 0 ||
- fraction.numerator.signum() == 0) {
- return ZERO;
- }
- return new BigFraction(numerator.multiply(fraction.numerator),
- denominator.multiply(fraction.denominator));
- }
-
- /**
- * Retrieves the sign of this fraction.
- *
- * @return -1 if the value is strictly negative, 1 if it is strictly
- * positive, 0 if it is 0.
- */
- public int signum() {
- final int numS = numerator.signum();
- final int denS = denominator.signum();
-
- if ((numS > 0 && denS > 0) ||
- (numS < 0 && denS < 0)) {
- return 1;
- } else if (numS == 0) {
- return 0;
- } else {
- return -1;
- }
- }
-
- /**
- * Return the additive inverse of this fraction, returning the result in
- * reduced form.
- *
- * @return the negation of this fraction.
- */
- @Override
- public BigFraction negate() {
- return new BigFraction(numerator.negate(), denominator);
- }
-
- /**
- * Returns a {@code BigFraction} whose value is
- * {@code (this<sup>exponent</sup>)}, returning the result in reduced form.
- *
- * @param exponent
- * exponent to which this {@code BigFraction} is to be
- * raised.
- * @return \(\mathit{this}^{\mathit{exponent}}\).
- */
- @Override
- public BigFraction pow(final int exponent) {
- if (exponent == 0) {
- return ONE;
- }
- if (numerator.signum() == 0) {
- return this;
- }
-
- if (exponent < 0) {
- return new BigFraction(denominator.pow(-exponent), numerator.pow(-exponent));
- }
- return new BigFraction(numerator.pow(exponent), denominator.pow(exponent));
- }
-
- /**
- * Returns a {@code BigFraction} whose value is
- * \(\mathit{this}^{\mathit{exponent}}\), returning the result in reduced form.
- *
- * @param exponent
- * exponent to which this {@code BigFraction} is to be raised.
- * @return \(\mathit{this}^{\mathit{exponent}}\) as a {@code BigFraction}.
- */
- public BigFraction pow(final long exponent) {
- if (exponent == 0) {
- return ONE;
- }
- if (numerator.signum() == 0) {
- return this;
- }
-
- if (exponent < 0) {
- return new BigFraction(ArithmeticUtils.pow(denominator, -exponent),
- ArithmeticUtils.pow(numerator, -exponent));
- }
- return new BigFraction(ArithmeticUtils.pow(numerator, exponent),
- ArithmeticUtils.pow(denominator, exponent));
- }
-
- /**
- * Returns a {@code BigFraction} whose value is
- * \(\mathit{this}^{\mathit{exponent}}\), returning the result in reduced form.
- *
- * @param exponent
- * exponent to which this {@code BigFraction} is to be raised.
- * @return \(\mathit{this}^{\mathit{exponent}}\) as a {@code BigFraction}.
- */
- public BigFraction pow(final BigInteger exponent) {
- if (exponent.signum() == 0) {
- return ONE;
- }
- if (numerator.signum() == 0) {
- return this;
- }
-
- if (exponent.signum() == -1) {
- final BigInteger eNeg = exponent.negate();
- return new BigFraction(ArithmeticUtils.pow(denominator, eNeg),
- ArithmeticUtils.pow(numerator, eNeg));
- }
- return new BigFraction(ArithmeticUtils.pow(numerator, exponent),
- ArithmeticUtils.pow(denominator, exponent));
- }
-
- /**
- * Returns a {@code double} whose value is
- * \(\mathit{this}^{\mathit{exponent}}\), returning the result in reduced form.
- *
- * @param exponent
- * exponent to which this {@code BigFraction} is to be raised.
- * @return \(\mathit{this}^{\mathit{exponent}}\).
- */
- public double pow(final double exponent) {
- return Math.pow(numerator.doubleValue(), exponent) /
- Math.pow(denominator.doubleValue(), exponent);
- }
-
- /**
- * Return the multiplicative inverse of this fraction.
- *
- * @return the reciprocal fraction.
- */
- @Override
- public BigFraction reciprocal() {
- return new BigFraction(denominator, numerator);
- }
-
- /**
- * Subtracts the value of an {@link BigInteger} from the value of this
- * {@code BigFraction}, returning the result in reduced form.
- *
- * @param bg the {@link BigInteger} to subtract, cannot be {@code null}.
- * @return a {@code BigFraction} instance with the resulting values.
- */
- public BigFraction subtract(final BigInteger bg) {
- if (bg.signum() == 0) {
- return this;
- }
- if (numerator.signum() == 0) {
- return of(bg.negate());
- }
-
- return new BigFraction(numerator.subtract(denominator.multiply(bg)), denominator);
- }
-
- /**
- * Subtracts the value of an {@code integer} from the value of this
- * {@code BigFraction}, returning the result in reduced form.
- *
- * @param i the {@code integer} to subtract.
- * @return a {@code BigFraction} instance with the resulting values.
- */
- public BigFraction subtract(final int i) {
- return subtract(BigInteger.valueOf(i));
- }
-
- /**
- * Subtracts the value of a {@code long} from the value of this
- * {@code BigFraction}, returning the result in reduced form.
- *
- * @param l the {@code long} to subtract.
- * @return a {@code BigFraction} instance with the resulting values.
- */
- public BigFraction subtract(final long l) {
- return subtract(BigInteger.valueOf(l));
- }
-
- /**
- * Subtracts the value of another fraction from the value of this one,
- * returning the result in reduced form.
- *
- * @param fraction {@link BigFraction} to subtract, must not be {@code null}.
- * @return a {@link BigFraction} instance with the resulting values
- */
- @Override
- public BigFraction subtract(final BigFraction fraction) {
- if (fraction.numerator.signum() == 0) {
- return this;
- }
- if (numerator.signum() == 0) {
- return fraction.negate();
- }
-
- final BigInteger num;
- final BigInteger den;
- if (denominator.equals(fraction.denominator)) {
- num = numerator.subtract(fraction.numerator);
- den = denominator;
- } else {
- num = (numerator.multiply(fraction.denominator)).subtract((fraction.numerator).multiply(denominator));
- den = denominator.multiply(fraction.denominator);
- }
- return new BigFraction(num, den);
- }
-
- /**
- * Returns the {@code String} representing this fraction, ie
- * "num / dem" or just "num" if the denominator is one.
- *
- * @return a string representation of the fraction.
- * @see java.lang.Object#toString()
- */
- @Override
- public String toString() {
- final String str;
- if (BigInteger.ONE.equals(denominator)) {
- str = numerator.toString();
- } else if (BigInteger.ZERO.equals(numerator)) {
- str = "0";
- } else {
- str = numerator + " / " + denominator;
- }
- return str;
- }
-
- /** {@inheritDoc} */
- @Override
- public BigFraction zero() {
- return ZERO;
- }
-
- /** {@inheritDoc} */
- @Override
- public BigFraction one() {
- return ONE;
- }
-
- /**
- * Parses a string that would be produced by {@link #toString()}
- * and instantiates the corresponding object.
- *
- * @param s String representation.
- * @return an instance.
- * @throws NumberFormatException if the string does not conform
- * to the specification.
- */
- public static BigFraction parse(String s) {
- s = s.replace(",", "");
- final int slashLoc = s.indexOf('/');
- // if no slash, parse as single number
- if (slashLoc == -1) {
- return BigFraction.of(new BigInteger(s.trim()));
- } else {
- final BigInteger num = new BigInteger(
- s.substring(0, slashLoc).trim());
- final BigInteger denom = new BigInteger(s.substring(slashLoc + 1).trim());
- return of(num, denom);
- }
- }
}
diff --git a/commons-numbers-fraction/src/main/java/org/apache/commons/numbers/fraction/Fraction.java b/commons-numbers-fraction/src/main/java/org/apache/commons/numbers/fraction/Fraction.java
index 00dd80e..8135438 100644
--- a/commons-numbers-fraction/src/main/java/org/apache/commons/numbers/fraction/Fraction.java
+++ b/commons-numbers-fraction/src/main/java/org/apache/commons/numbers/fraction/Fraction.java
@@ -35,23 +35,61 @@ public final class Fraction
implements Comparable<Fraction>,
NativeOperators<Fraction>,
Serializable {
- /** A fraction representing "1". */
- public static final Fraction ONE = new Fraction(1, 1);
-
/** A fraction representing "0". */
public static final Fraction ZERO = new Fraction(0, 1);
+ /** A fraction representing "1". */
+ public static final Fraction ONE = new Fraction(1, 1);
+
/** Serializable version identifier. */
private static final long serialVersionUID = 20190701L;
/** The default epsilon used for convergence. */
private static final double DEFAULT_EPSILON = 1e-5;
+ /** The numerator of this fraction reduced to lowest terms. */
+ private final int numerator;
+
/** The denominator of this fraction reduced to lowest terms. */
private final int denominator;
- /** The numerator of this fraction reduced to lowest terms. */
- private final int numerator;
+
+ /**
+ * Constructs an instance.
+ *
+ * @param num Numerator.
+ * @param den Denominator.
+ * @throws ArithmeticException if the denominator is {@code zero}
+ * or if integer overflow occurs.
+ */
+ private Fraction(int num, int den) {
+ if (den == 0) {
+ throw new ArithmeticException("division by zero");
+ }
+
+ if (num == den) {
+ numerator = 1;
+ denominator = 1;
+ } else {
+ // If num and den are both 2^-31, or if one is 0 and the other is 2^-31,
+ // the calculation of the gcd below will fail. Ensure that this does not
+ // happen by dividing both by 2 in case both are even.
+ if (((num | den) & 1) == 0) {
+ num >>= 1;
+ den >>= 1;
+ }
+
+ // Reduce numerator and denominator by greatest common divisor.
+ final int d = ArithmeticUtils.gcd(num, den);
+ if (d > 1) {
+ num /= d;
+ den /= d;
+ }
+
+ numerator = num;
+ denominator = den;
+ }
+ }
/**
* Create a fraction given the double value and either the maximum error
@@ -85,7 +123,10 @@ public final class Fraction
* @throws ArithmeticException if the continued fraction failed
* to converge.
*/
- private Fraction(double value, double epsilon, int maxDenominator, int maxIterations) {
+ private Fraction(final double value,
+ final double epsilon,
+ final int maxDenominator,
+ final int maxIterations) {
final long overflow = Integer.MAX_VALUE;
double r0 = value;
long a0 = (long)Math.floor(r0);
@@ -157,43 +198,6 @@ public final class Fraction
}
/**
- * Constructs an instance.
- *
- * @param num Numerator.
- * @param den Denominator.
- * @throws ArithmeticException if the denominator is {@code zero}
- * or if integer overflow occurs.
- */
- private Fraction(int num, int den) {
- if (den == 0) {
- throw new ArithmeticException("division by zero");
- }
-
- if (num == den) {
- numerator = 1;
- denominator = 1;
- } else {
- // If num and den are both 2^-31, or if one is 0 and the other is 2^-31,
- // the calculation of the gcd below will fail. Ensure that this does not
- // happen by dividing both by 2 in case both are even.
- if (((num | den) & 1) == 0) {
- num >>= 1;
- den >>= 1;
- }
-
- // Reduce numerator and denominator by greatest common divisor.
- final int d = ArithmeticUtils.gcd(num, den);
- if (d > 1) {
- num /= d;
- den /= d;
- }
-
- numerator = num;
- denominator = den;
- }
- }
-
- /**
* Create a fraction given the double value.
*
* @param value Value to convert to a fraction.
@@ -201,7 +205,7 @@ public final class Fraction
* converge.
* @return a new instance.
*/
- public static Fraction from(double value) {
+ public static Fraction from(final double value) {
return from(value, DEFAULT_EPSILON, 100);
}
@@ -223,7 +227,9 @@ public final class Fraction
* converge.
* @return a new instance.
*/
- public static Fraction from(double value, double epsilon, int maxIterations) {
+ public static Fraction from(final double value,
+ final double epsilon,
+ final int maxIterations) {
return new Fraction(value, epsilon, Integer.MAX_VALUE, maxIterations);
}
@@ -243,7 +249,8 @@ public final class Fraction
* converge.
* @return a new instance.
*/
- public static Fraction from(double value, int maxDenominator) {
+ public static Fraction from(final double value,
+ final int maxDenominator) {
return new Fraction(value, 0, maxDenominator, 100);
}
@@ -253,7 +260,7 @@ public final class Fraction
* @param num Numerator.
* @return a new instance.
*/
- public static Fraction of(int num) {
+ public static Fraction of(final int num) {
return of(num, 1);
}
@@ -267,11 +274,73 @@ public final class Fraction
* or if integer overflow occurs.
* @return a new instance.
*/
- public static Fraction of(int num, int den) {
+ public static Fraction of(final int num, final int den) {
return new Fraction(num, den);
}
/**
+ * Parses a string that would be produced by {@link #toString()}
+ * and instantiates the corresponding object.
+ *
+ * @param s String representation.
+ * @return an instance.
+ * @throws NumberFormatException if the string does not conform to the
+ * specification.
+ */
+ public static Fraction parse(String s) {
+ final int slashLoc = s.indexOf('/');
+ // if no slash, parse as single number
+ if (slashLoc == -1) {
+ return Fraction.of(Integer.parseInt(s.trim()));
+ } else {
+ final int num = Integer.parseInt(s.substring(0, slashLoc).trim());
+ final int denom = Integer.parseInt(s.substring(slashLoc + 1).trim());
+ return of(num, denom);
+ }
+ }
+
+ @Override
+ public Fraction zero() {
+ return ZERO;
+ }
+
+ @Override
+ public Fraction one() {
+ return ONE;
+ }
+
+ /**
+ * @return the numerator.
+ */
+ public int getNumerator() {
+ return numerator;
+ }
+
+ /**
+ * @return the denominator.
+ */
+ public int getDenominator() {
+ return denominator;
+ }
+
+ /**
+ * Retrieves the sign of this fraction.
+ *
+ * @return -1 if the value is strictly negative, 1 if it is strictly
+ * positive, 0 if it is 0.
+ */
+ public int signum() {
+ if ((numerator > 0 && denominator > 0) ||
+ (numerator < 0 && denominator < 0)) {
+ return 1;
+ } else if (numerator == 0) {
+ return 0;
+ } else {
+ return -1;
+ }
+ }
+
+ /**
* Returns the absolute value of this fraction.
*
* @return the absolute value.
@@ -283,56 +352,36 @@ public final class Fraction
}
/**
- * Compares this object to another based on size.
+ * Computes the additive inverse of this fraction.
*
- * @param other Object to compare to.
- * @return -1 if this is less than {@code object}, +1 if this is greater
- * than {@code object}, 0 if they are equal.
+ * @return the opposite.
*/
@Override
- public int compareTo(Fraction other) {
- return Long.compare(((long) numerator) * other.denominator,
- ((long) denominator) * other.numerator);
+ public Fraction negate() {
+ return numerator == Integer.MIN_VALUE ?
+ new Fraction(numerator, -denominator) :
+ new Fraction(-numerator, denominator);
}
/**
- * Retrieves the {@code double} value closest to this fraction.
- * This calculates the fraction as numerator divided by denominator.
+ * Computes the multiplicative inverse of this fraction.
*
- * @return the fraction as a {@code double}.
+ * @return the reciprocal.
*/
@Override
- public double doubleValue() {
- return (double) numerator / (double) denominator;
+ public Fraction reciprocal() {
+ return new Fraction(denominator, numerator);
}
/**
- * Test for the equality of two fractions.
- * If the lowest term numerator and denominators are the same for
- * both fractions, the two fractions are considered to be equal.
- * @param other Fraction to test for equality with.
- * @return {@code true} if the two fractions are equal, {@code false}
- * otherwise.
+ * Retrieves the {@code double} value closest to this fraction.
+ * This calculates the fraction as numerator divided by denominator.
+ *
+ * @return the fraction as a {@code double}.
*/
@Override
- public boolean equals(Object other) {
- if (this == other) {
- return true;
- }
-
- if (other instanceof Fraction) {
- // Since fractions are always in lowest terms, numerators and
- // denominators can be compared directly for equality.
- final Fraction rhs = (Fraction) other;
- if (signum() == rhs.signum()) {
- return Math.abs(numerator) == Math.abs(rhs.numerator) &&
- Math.abs(denominator) == Math.abs(rhs.denominator);
- } else {
- return false;
- }
- }
-
- return false;
+ public double doubleValue() {
+ return (double) numerator / (double) denominator;
}
/**
@@ -347,26 +396,6 @@ public final class Fraction
}
/**
- * @return the denominator.
- */
- public int getDenominator() {
- return denominator;
- }
-
- /**
- * @return the numerator.
- */
- public int getNumerator() {
- return numerator;
- }
-
- /** {@inheritDoc} */
- @Override
- public int hashCode() {
- return 37 * (37 * 17 + numerator) + denominator;
- }
-
- /**
* Retrieves the whole number part of the fraction.
*
* @return the largest {@code int} value that is not larger than
@@ -389,42 +418,13 @@ public final class Fraction
}
/**
- * Retrieves the sign of this fraction.
- *
- * @return -1 if the value is strictly negative, 1 if it is strictly
- * positive, 0 if it is 0.
- */
- public int signum() {
- if ((numerator > 0 && denominator > 0) ||
- (numerator < 0 && denominator < 0)) {
- return 1;
- } else if (numerator == 0) {
- return 0;
- } else {
- return -1;
- }
- }
-
- /**
- * Computes the additive inverse of this fraction.
- *
- * @return the opposite.
- */
- @Override
- public Fraction negate() {
- return numerator == Integer.MIN_VALUE ?
- new Fraction(numerator, -denominator) :
- new Fraction(-numerator, denominator);
- }
-
- /**
- * Computes the multiplicative inverse of this fraction.
+ * Adds an integer to the fraction.
*
- * @return the reciprocal.
+ * @param i Value to add.
+ * @return {@code this + i}.
*/
- @Override
- public Fraction reciprocal() {
- return new Fraction(denominator, numerator);
+ public Fraction add(final int i) {
+ return new Fraction(numerator + i * denominator, denominator);
}
/**
@@ -443,13 +443,13 @@ public final class Fraction
}
/**
- * Adds an integer to the fraction.
+ * Subtracts an integer from this fraction.
*
- * @param i Value to add.
- * @return {@code this + i}.
+ * @param i Value to subtract.
+ * @return {@code this - i}.
*/
- public Fraction add(final int i) {
- return new Fraction(numerator + i * denominator, denominator);
+ public Fraction subtract(final int i) {
+ return new Fraction(numerator - i * denominator, denominator);
}
/**
@@ -467,16 +467,6 @@ public final class Fraction
}
/**
- * Subtracts an integer from this fraction.
- *
- * @param i Value to subtract.
- * @return {@code this - i}.
- */
- public Fraction subtract(final int i) {
- return new Fraction(numerator - i * denominator, denominator);
- }
-
- /**
* Implements add and subtract using algorithm described in Knuth 4.5.1.
*
* @param fraction Fraction to add or subtract.
@@ -529,6 +519,17 @@ public final class Fraction
}
/**
+ * Multiplies the fraction by an integer.
+ *
+ * @param i Value to multiply by.
+ * @return {@code this * i}.
+ */
+ @Override
+ public Fraction multiply(final int i) {
+ return multiply(of(i));
+ }
+
+ /**
* Multiplies the value of this fraction by another, returning the
* result in reduced form.
*
@@ -553,14 +554,13 @@ public final class Fraction
}
/**
- * Multiplies the fraction by an integer.
+ * Divides the fraction by an integer.
*
- * @param i Value to multiply by.
+ * @param i Value to divide by.
* @return {@code this * i}.
*/
- @Override
- public Fraction multiply(final int i) {
- return multiply(of(i));
+ public Fraction divide(final int i) {
+ return divide(of(i));
}
/**
@@ -583,36 +583,38 @@ public final class Fraction
}
/**
- * Divides the fraction by an integer.
+ * {@inheritDoc}
*
- * @param i Value to divide by.
- * @return {@code this * i}.
- */
- public Fraction divide(final int i) {
- return divide(of(i));
- }
-
- /**
- * @param n Power.
- * @return <code>this<sup>n</sup></code>.
+ * @param exponent {@inheritDoc}
+ * @return <code>this<sup>exponent</sup></code>.
*/
@Override
- public Fraction pow(final int n) {
- if (n == 0) {
+ public Fraction pow(final int exponent) {
+ if (exponent == 0) {
return ONE;
}
if (numerator == 0) {
return this;
}
- return n < 0 ?
- new Fraction(ArithmeticUtils.pow(denominator, -n),
- ArithmeticUtils.pow(numerator, -n)) :
- new Fraction(ArithmeticUtils.pow(numerator, n),
- ArithmeticUtils.pow(denominator, n));
+ return exponent < 0 ?
+ new Fraction(ArithmeticUtils.pow(denominator, -exponent),
+ ArithmeticUtils.pow(numerator, -exponent)) :
+ new Fraction(ArithmeticUtils.pow(numerator, exponent),
+ ArithmeticUtils.pow(denominator, exponent));
}
- /** {@inheritDoc} */
+ /**
+ * Returns the {@code String} representing this fraction.
+ * Uses:
+ * <ul>
+ * <li>{@code "0"} if {@code numerator} is zero.
+ * <li>{@code "numerator"} if {@code denominator} is one.
+ * <li>{@code "numerator / denominator"} for all other cases.
+ * </ul>
+ *
+ * @return a string representation of the fraction.
+ */
@Override
public String toString() {
final String str;
@@ -626,36 +628,46 @@ public final class Fraction
return str;
}
- /** {@inheritDoc} */
- @Override
- public Fraction zero() {
- return ZERO;
- }
-
- /** {@inheritDoc} */
+ /**
+ * Compares this object with the specified object for order using the signed magnitude.
+ *
+ * @param other {@inheritDoc}
+ * @return {@inheritDoc}
+ */
@Override
- public Fraction one() {
- return ONE;
+ public int compareTo(Fraction other) {
+ return Long.compare(((long) numerator) * other.denominator,
+ ((long) denominator) * other.numerator);
}
/**
- * Parses a string that would be produced by {@link #toString()}
- * and instantiates the corresponding object.
+ * Test for equality with another object. If the other object is a {@code Fraction} then a
+ * comparison is made of the sign and magnitude; otherwise {@code false} is returned.
*
- * @param s String representation.
- * @return an instance.
- * @throws NumberFormatException if the string does not conform to the
- * specification.
+ * @param other {@inheritDoc}
+ * @return {@inheritDoc}
*/
- public static Fraction parse(String s) {
- final int slashLoc = s.indexOf('/');
- // if no slash, parse as single number
- if (slashLoc == -1) {
- return Fraction.of(Integer.parseInt(s.trim()));
- } else {
- final int num = Integer.parseInt(s.substring(0, slashLoc).trim());
- final int denom = Integer.parseInt(s.substring(slashLoc + 1).trim());
- return of(num, denom);
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
}
+
+ if (other instanceof Fraction) {
+ // Since fractions are always in lowest terms, numerators and
+ // denominators can be compared directly for equality.
+ final Fraction rhs = (Fraction) other;
+ if (signum() == rhs.signum()) {
+ return Math.abs(numerator) == Math.abs(rhs.numerator) &&
+ Math.abs(denominator) == Math.abs(rhs.denominator);
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return 37 * (37 * 17 + numerator) + denominator;
}
}