From 80419081ac3fb9f525e6cada75a752519499e1c3 Mon Sep 17 00:00:00 2001 From: Luc Maisonobe Date: Mon, 30 Mar 2009 15:48:56 +0000 Subject: [PATCH] optimized some fraction operations (mainly pow) replaced pow(BigFraction) by pow(double) as it already converted the argument to double upon entry added tests for pow git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@760016 13f79535-47bb-0310-9956-ffa450edef68 --- .../commons/math/fraction/BigFraction.java | 327 +++++++++--------- .../math/fraction/BigFractionTest.java | 13 + 2 files changed, 184 insertions(+), 156 deletions(-) diff --git a/src/java/org/apache/commons/math/fraction/BigFraction.java b/src/java/org/apache/commons/math/fraction/BigFraction.java index a2ce3a38a..9c957ec01 100644 --- a/src/java/org/apache/commons/math/fraction/BigFraction.java +++ b/src/java/org/apache/commons/math/fraction/BigFraction.java @@ -20,6 +20,7 @@ import java.math.BigDecimal; import java.math.BigInteger; import org.apache.commons.math.MathRuntimeException; +import org.apache.commons.math.util.MathUtils; /** * Representation of a rational number without any overflow. This class is @@ -457,7 +458,35 @@ public class BigFraction extends Number implements Comparable { * if the {@link BigInteger} is null. */ public BigFraction add(final BigInteger bg) { - return add(new BigFraction(bg, BigInteger.ONE)); + return new BigFraction(numerator.add(denominator.multiply(bg)), denominator); + } + + /** + *

+ * Adds the value of this fraction to the passed integer, returning + * the result in reduced form. + *

+ * + * @param i + * the integer to add. + * @return a BigFraction instance with the resulting values. + */ + public BigFraction add(final int i) { + return add(BigInteger.valueOf(i)); + } + + /** + *

+ * Adds the value of this fraction to the passed long, returning + * the result in reduced form. + *

+ * + * @param l + * the long to add. + * @return a BigFraction instance with the resulting values. + */ + public BigFraction add(final long l) { + return add(BigInteger.valueOf(l)); } /** @@ -491,34 +520,6 @@ public class BigFraction extends Number implements Comparable { } - /** - *

- * Adds the value of this fraction to the passed integer, returning - * the result in reduced form. - *

- * - * @param i - * the integer to add. - * @return a BigFraction instance with the resulting values. - */ - public BigFraction add(final int i) { - return add(new BigFraction(i, 1)); - } - - /** - *

- * Adds the value of this fraction to the passed long, returning - * the result in reduced form. - *

- * - * @param l - * the long to add. - * @return a BigFraction instance with the resulting values. - */ - public BigFraction add(final long l) { - return add(new BigFraction(l, 1L)); - } - /** *

* Gets the fraction as a BigDecimal. This calculates the @@ -602,9 +603,46 @@ public class BigFraction extends Number implements Comparable { * @return a {@link BigFraction} instance with the resulting values. * @throws NullPointerException * if the BigInteger is null. + * @throws ArithmeticException + * if the fraction to divide by is zero. */ public BigFraction divide(final BigInteger bg) { - return divide(new BigFraction(bg, BigInteger.ONE)); + if (BigInteger.ZERO.equals(bg)) { + throw MathRuntimeException.createArithmeticException("denominator must be different from 0"); + } + return new BigFraction(numerator, denominator.multiply(bg)); + } + + /** + *

+ * Divide the value of this fraction by the passed int, ie + * "this * 1 / i", returning the result in reduced form. + *

+ * + * @param i + * the int to divide by. + * @return a {@link BigFraction} instance with the resulting values. + * @throws ArithmeticException + * if the fraction to divide by is zero. + */ + public BigFraction divide(final int i) { + return divide(BigInteger.valueOf(i)); + } + + /** + *

+ * Divide the value of this fraction by the passed long, ie + * "this * 1 / l", returning the result in reduced form. + *

+ * + * @param l + * the long to divide by. + * @return a {@link BigFraction} instance with the resulting values. + * @throws ArithmeticException + * if the fraction to divide by is zero. + */ + public BigFraction divide(final long l) { + return divide(BigInteger.valueOf(l)); } /** @@ -629,34 +667,6 @@ public class BigFraction extends Number implements Comparable { return multiply(fraction.reciprocal()); } - /** - *

- * Divide the value of this fraction by the passed int, ie - * "this * 1 / i", returning the result in reduced form. - *

- * - * @param i - * the int to divide by. - * @return a {@link BigFraction} instance with the resulting values. - */ - public BigFraction divide(final int i) { - return divide(new BigFraction(i, 1)); - } - - /** - *

- * Divide the value of this fraction by the passed long, ie - * "this * 1 / l", returning the result in reduced form. - *

- * - * @param l - * the long to divide by. - * @return a {@link BigFraction} instance with the resulting values. - */ - public BigFraction divide(final long l) { - return divide(new BigFraction(l, 1L)); - } - /** *

* Gets the fraction as a double. This calculates the fraction as @@ -838,6 +848,34 @@ public class BigFraction extends Number implements Comparable { return new BigFraction(bg.multiply(numerator), denominator); } + /** + *

+ * Multiply the value of this fraction by the passed int, returning + * the result in reduced form. + *

+ * + * @param i + * the int to multiply by. + * @return a {@link BigFraction} instance with the resulting values. + */ + public BigFraction multiply(final int i) { + return multiply(BigInteger.valueOf(i)); + } + + /** + *

+ * Multiply the value of this fraction by the passed long, + * returning the result in reduced form. + *

+ * + * @param l + * the long to multiply by. + * @return a {@link BigFraction} instance with the resulting values. + */ + public BigFraction multiply(final long l) { + return multiply(BigInteger.valueOf(l)); + } + /** *

* Multiplies the value of this fraction by another, returning the result in @@ -860,34 +898,6 @@ public class BigFraction extends Number implements Comparable { return ret; } - /** - *

- * Multiply the value of this fraction by the passed int, returning - * the result in reduced form. - *

- * - * @param i - * the int to multiply by. - * @return a {@link BigFraction} instance with the resulting values. - */ - public BigFraction multiply(final int i) { - return multiply(new BigFraction(i, 1)); - } - - /** - *

- * Multiply the value of this fraction by the passed long, - * returning the result in reduced form. - *

- * - * @param l - * the long to multiply by. - * @return a {@link BigFraction} instance with the resulting values. - */ - public BigFraction multiply(final long l) { - return multiply(new BigFraction(l, 1L)); - } - /** *

* Return the additive inverse of this fraction, returning the result in @@ -912,44 +922,6 @@ public class BigFraction extends Number implements Comparable { return (numerator.divide(denominator)).multiply(ONE_HUNDRED_DOUBLE).doubleValue(); } - /** - *

- * Returns a BigFraction whose value is - * (thisexponent), returning the result in reduced form. - *

- * - * @param exponent - * exponent to which this BigFraction is to be raised. - * @return thisexponent as a BigFraction. - */ - public BigFraction pow(final BigInteger exponent) { - BigFraction ret = this; - if (!BigInteger.ONE.equals(exponent)) { - ret = ONE; - if (!BigInteger.ZERO.equals(exponent)) { - for (BigInteger bg = BigInteger.ONE; bg.compareTo(exponent) < 0; bg = bg.add(BigInteger.ONE)) { - ret = ret.multiply(this); - } - } - } - - return ret; - } - - /** - *

- * Returns a BigFraction whose value is - * (thisexponent), returning the result in reduced form. - *

- * - * @param exponent - * exponent to which this BigFraction is to be raised. - * @return thisexponent. - */ - public double pow(final BigFraction exponent) { - return Math.pow(numerator.doubleValue(), exponent.doubleValue()) / Math.pow(denominator.doubleValue(), exponent.doubleValue()); - } - /** *

* Returns a integer whose value is @@ -962,7 +934,10 @@ public class BigFraction extends Number implements Comparable { * @return thisexponent. */ public BigFraction pow(final int exponent) { - return pow(BigInteger.valueOf(exponent)); + if (exponent < 0) { + return new BigFraction(denominator.pow(-exponent), numerator.pow(-exponent)); + } + return new BigFraction(numerator.pow(exponent), denominator.pow(exponent)); } /** @@ -976,7 +951,47 @@ public class BigFraction extends Number implements Comparable { * @return thisexponent as a BigFraction. */ public BigFraction pow(final long exponent) { - return pow(BigInteger.valueOf(exponent)); + if (exponent < 0) { + return new BigFraction(MathUtils.pow(denominator, -exponent), + MathUtils.pow(numerator, -exponent)); + } + return new BigFraction(MathUtils.pow(numerator, exponent), + MathUtils.pow(denominator, exponent)); + } + + /** + *

+ * Returns a BigFraction whose value is + * (thisexponent), returning the result in reduced form. + *

+ * + * @param exponent + * exponent to which this BigFraction is to be raised. + * @return thisexponent as a BigFraction. + */ + public BigFraction pow(final BigInteger exponent) { + if (exponent.compareTo(BigInteger.ZERO) < 0) { + final BigInteger eNeg = exponent.negate(); + return new BigFraction(MathUtils.pow(denominator, eNeg), + MathUtils.pow(numerator, eNeg)); + } + return new BigFraction(MathUtils.pow(numerator, exponent), + MathUtils.pow(denominator, exponent)); + } + + /** + *

+ * Returns a double whose value is + * (thisexponent), returning the result in reduced form. + *

+ * + * @param exponent + * exponent to which this BigFraction is to be raised. + * @return thisexponent. + */ + public double pow(final double exponent) { + return Math.pow(numerator.doubleValue(), exponent) / + Math.pow(denominator.doubleValue(), exponent); } /** @@ -1017,7 +1032,36 @@ public class BigFraction extends Number implements Comparable { * if the {@link BigInteger} is null. */ public BigFraction subtract(final BigInteger bg) { - return subtract(new BigFraction(bg, BigInteger.valueOf(1))); + return new BigFraction(numerator.subtract(denominator.multiply(bg)), denominator); + } + + /** + *

+ * Subtracts the value of an integer from the value of this one, + * returning the result in reduced form. + *

+ * + * @param i + * the integer to subtract. + * @return a BigFraction instance with the resulting values. + */ + public BigFraction subtract(final int i) { + return subtract(BigInteger.valueOf(i)); + } + + /** + *

+ * Subtracts the value of an integer from the value of this one, + * returning the result in reduced form. + *

+ * + * @param l + * the long to subtract. + * @return a BigFraction instance with the resulting values, or + * this object if the long is zero. + */ + public BigFraction subtract(final long l) { + return subtract(BigInteger.valueOf(l)); } /** @@ -1051,35 +1095,6 @@ public class BigFraction extends Number implements Comparable { } - /** - *

- * Subtracts the value of an integer from the value of this one, - * returning the result in reduced form. - *

- * - * @param i - * the integer to subtract. - * @return a BigFraction instance with the resulting values. - */ - public BigFraction subtract(final int i) { - return subtract(new BigFraction(i, 1)); - } - - /** - *

- * Subtracts the value of an integer from the value of this one, - * returning the result in reduced form. - *

- * - * @param l - * the long to subtract. - * @return a BigFraction instance with the resulting values, or - * this object if the long is zero. - */ - public BigFraction subtract(final long l) { - return subtract(new BigFraction(l, 1L)); - } - /** *

* Returns the String representing this fraction, ie diff --git a/src/test/org/apache/commons/math/fraction/BigFractionTest.java b/src/test/org/apache/commons/math/fraction/BigFractionTest.java index 42e448fc4..c8be9a656 100644 --- a/src/test/org/apache/commons/math/fraction/BigFractionTest.java +++ b/src/test/org/apache/commons/math/fraction/BigFractionTest.java @@ -537,4 +537,17 @@ public class BigFractionTest extends TestCase { assertEquals(BigFraction.getReducedFraction(2, Integer.MIN_VALUE).getNumeratorAsInt(), -1); assertEquals(BigFraction.getReducedFraction(1, -1).getNumeratorAsInt(), -1); } + + public void testPow() { + assertEquals(new BigFraction(8192, 1594323), new BigFraction(2, 3).pow(13)); + assertEquals(new BigFraction(8192, 1594323), new BigFraction(2, 3).pow(13l)); + assertEquals(new BigFraction(8192, 1594323), new BigFraction(2, 3).pow(BigInteger.valueOf(13l))); + assertEquals(BigFraction.ONE, new BigFraction(2, 3).pow(0)); + assertEquals(BigFraction.ONE, new BigFraction(2, 3).pow(0l)); + assertEquals(BigFraction.ONE, new BigFraction(2, 3).pow(BigInteger.valueOf(0l))); + assertEquals(new BigFraction(1594323, 8192), new BigFraction(2, 3).pow(-13)); + assertEquals(new BigFraction(1594323, 8192), new BigFraction(2, 3).pow(-13l)); + assertEquals(new BigFraction(1594323, 8192), new BigFraction(2, 3).pow(BigInteger.valueOf(-13l))); + } + }