added fraction class and fraction formatting classes.
git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/math/trunk@151479 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
3bad03d075
commit
d53731afbe
|
@ -36,10 +36,7 @@ maven.xdoc.developmentProcessUrl=http://jakarta.apache.org/commons/charter.html
|
|||
|
||||
maven.javadoc.links = http://java.sun.com/j2se/1.4.2/docs/api/,\
|
||||
http://jakarta.apache.org/commons/collections/api/,\
|
||||
http://jakarta.apache.org/commons/beanutils/api/,\
|
||||
http://jakarta.apache.org/commons/lang/api/,\
|
||||
http://jakarta.apache.org/commons/discovery/api/,\
|
||||
http://jakarta.apache.org/commons/logging/api/
|
||||
http://jakarta.apache.org/commons/discovery/api/
|
||||
|
||||
maven.changes.issue.template=http://issues.apache.org/bugzilla/show_bug.cgi?id=%ISSUE%
|
||||
|
||||
|
|
|
@ -0,0 +1,338 @@
|
|||
/*
|
||||
* Copyright 2005 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.math.fraction;
|
||||
|
||||
import org.apache.commons.math.ConvergenceException;
|
||||
import org.apache.commons.math.util.MathUtils;
|
||||
|
||||
/**
|
||||
* Representation of a rational number.
|
||||
*
|
||||
* @author Apache Software Foundation
|
||||
* @version $Revision: $ $Date: $
|
||||
*/
|
||||
public class Fraction extends Number implements Comparable {
|
||||
|
||||
/** A fraction representing "1 / 1". */
|
||||
public static final Fraction ONE = new Fraction(1, 1);
|
||||
|
||||
/** A fraction representing "0 / 1". */
|
||||
public static final Fraction ZERO = new Fraction(0, 1);
|
||||
|
||||
/** Serializable version identifier */
|
||||
static final long serialVersionUID = 65382027393090L;
|
||||
|
||||
/** The denominator. */
|
||||
private int denominator;
|
||||
|
||||
/** The numerator. */
|
||||
private int numerator;
|
||||
|
||||
/**
|
||||
* Create a fraction given the double value.
|
||||
* @param value the double value to convert to a fraction.
|
||||
* @throws ConvergenceException if the continued fraction failed to
|
||||
* converge.
|
||||
*/
|
||||
public Fraction(double value) throws ConvergenceException {
|
||||
this(value, 1.0e-5, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a fraction given the double value.
|
||||
* <p>
|
||||
* References:
|
||||
* <ul>
|
||||
* <li><a href="http://mathworld.wolfram.com/ContinuedFraction.html">
|
||||
* Continued Fraction</a> equations (11) and (22)-(26)</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
* @param value the double value to convert to a fraction.
|
||||
* @param epsilon maximum error allowed. The resulting fraction is within
|
||||
* <code>epsilon</code> of <code>value</code>, in absolute terms.
|
||||
* @param maxIterations maximum number of convergents
|
||||
* @throws ConvergenceException if the continued fraction failed to
|
||||
* converge.
|
||||
*/
|
||||
public Fraction(double value, double epsilon, int maxIterations)
|
||||
throws ConvergenceException
|
||||
{
|
||||
double r0 = value;
|
||||
int a0 = (int)Math.floor(r0);
|
||||
|
||||
int p0 = 1;
|
||||
int q0 = 0;
|
||||
int p1 = a0;
|
||||
int q1 = 1;
|
||||
|
||||
int p2 = 0;
|
||||
int q2 = 1;
|
||||
|
||||
int n = 0;
|
||||
boolean stop = false;
|
||||
do {
|
||||
++n;
|
||||
double r1 = 1.0 / (r0 - a0);
|
||||
int a1 = (int)Math.floor(r1);
|
||||
p2 = (a1 * p1) + p0;
|
||||
q2 = (a1 * q1) + q0;
|
||||
|
||||
double convergent = (double)p2 / (double)q2;
|
||||
if (n < maxIterations && Math.abs(convergent - value) > epsilon) {
|
||||
p0 = p1;
|
||||
p1 = p2;
|
||||
q0 = q1;
|
||||
q1 = q2;
|
||||
a0 = a1;
|
||||
r0 = r1;
|
||||
} else {
|
||||
stop = true;
|
||||
}
|
||||
} while (!stop);
|
||||
|
||||
if (n >= maxIterations) {
|
||||
throw new ConvergenceException(
|
||||
"Unable to convert double to fraction");
|
||||
}
|
||||
|
||||
this.numerator = p2;
|
||||
this.denominator = q2;
|
||||
reduce();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a fraction given the numerator and denominator. The fraction is
|
||||
* reduced to lowest terms.
|
||||
* @param num the numerator.
|
||||
* @param den the denominator.
|
||||
*/
|
||||
public Fraction(int num, int den) {
|
||||
super();
|
||||
this.numerator = num;
|
||||
this.denominator = den;
|
||||
reduce();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the absolute value of this fraction.
|
||||
* @return the absolute value.
|
||||
*/
|
||||
public Fraction abs() {
|
||||
Fraction ret;
|
||||
if (numerator >= 0) {
|
||||
ret = this;
|
||||
} else {
|
||||
ret = negate();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the sum of this fraction and the given fraction. The returned
|
||||
* fraction is reduced to lowest terms.
|
||||
*
|
||||
* @param rhs the other fraction.
|
||||
* @return the fraction sum in lowest terms.
|
||||
*/
|
||||
public Fraction add(Fraction rhs) {
|
||||
int den = MathUtils.lcm(denominator, rhs.denominator);
|
||||
int num = (numerator * (den / denominator)) +
|
||||
(rhs.numerator * (den / rhs.denominator));
|
||||
return new Fraction(num, den);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares this object to another based on size.
|
||||
* @param object the object to compare to
|
||||
* @return -1 if this is less than <tt>object</tt>, +1 if this is greater
|
||||
* than <tt>object</tt>, 0 if they are equal.
|
||||
*/
|
||||
public int compareTo(Object object) {
|
||||
int ret = 0;
|
||||
|
||||
if (this != object) {
|
||||
Fraction other = (Fraction)object;
|
||||
double first = doubleValue();
|
||||
double second = other.doubleValue();
|
||||
|
||||
if (first < second) {
|
||||
ret = -1;
|
||||
} else if (first > second) {
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the quotient of this fraction and the given fraction. The
|
||||
* returned fraction is reduced to lowest terms.
|
||||
* @param rhs the other fraction.
|
||||
* @return the fraction quotient in lowest terms.
|
||||
*/
|
||||
public Fraction divide(Fraction rhs) {
|
||||
return multiply(rhs.reciprocal());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the fraction as a <tt>double</tt>. This calculates the fraction as
|
||||
* the numerator divided by denominator.
|
||||
* @return the fraction as a <tt>double</tt>
|
||||
*/
|
||||
public double doubleValue() {
|
||||
return (double)numerator / (double)denominator;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @return true if two fractions are equal, false if object is
|
||||
* <tt>null</tt>, not an instance of {@link Fraction}, or not equal
|
||||
* to this fraction instance.
|
||||
*/
|
||||
public boolean equals(Object other) {
|
||||
boolean ret;
|
||||
|
||||
if (this == other) {
|
||||
ret = true;
|
||||
} else if (other == null) {
|
||||
ret = false;
|
||||
} else {
|
||||
try {
|
||||
// since fractions are always in lowest terms, numerators and
|
||||
// denominators can be compared directly for equality.
|
||||
Fraction rhs = (Fraction)other;
|
||||
ret = (numerator == rhs.numerator) &&
|
||||
(denominator == rhs.denominator);
|
||||
} catch (ClassCastException ex) {
|
||||
// ignore exception
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the fraction as a <tt>float</tt>. This calculates the fraction as
|
||||
* the numerator divided by denominator.
|
||||
* @return the fraction as a <tt>float</tt>
|
||||
*/
|
||||
public float floatValue() {
|
||||
return (float)doubleValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the denominator.
|
||||
* @return the denominator.
|
||||
*/
|
||||
public int getDenominator() {
|
||||
return denominator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the numerator.
|
||||
* @return the numerator.
|
||||
*/
|
||||
public int getNumerator() {
|
||||
return numerator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a hashCode for the fraction.
|
||||
* @return a hash code value for this object
|
||||
*/
|
||||
public int hashCode() {
|
||||
return 37 * (37 * 17 + getNumerator()) + getDenominator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the fraction as an <tt>int</tt>. This returns the whole number part
|
||||
* of the fraction.
|
||||
* @return the whole number fraction part
|
||||
*/
|
||||
public int intValue() {
|
||||
return (int)doubleValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the fraction as a <tt>long</tt>. This returns the whole number part
|
||||
* of the fraction.
|
||||
* @return the whole number fraction part
|
||||
*/
|
||||
public long longValue() {
|
||||
return (long)doubleValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the product of this fraction and the given fraction. The returned
|
||||
* fraction is reduced to lowest terms.
|
||||
* @param rhs the other fraction.
|
||||
* @return the fraction product in lowest terms.
|
||||
*/
|
||||
public Fraction multiply(Fraction rhs) {
|
||||
return new Fraction(numerator * rhs.numerator,
|
||||
denominator * rhs.denominator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the additive inverse of this fraction.
|
||||
* @return the negation of this fraction.
|
||||
*/
|
||||
public Fraction negate() {
|
||||
return new Fraction(-numerator, denominator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the multiplicative inverse of this fraction.
|
||||
* @return the reciprocal fraction
|
||||
*/
|
||||
public Fraction reciprocal() {
|
||||
return new Fraction(denominator, numerator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the difference between this fraction and the given fraction. The
|
||||
* returned fraction is reduced to lowest terms.
|
||||
* @param rhs the other fraction.
|
||||
* @return the fraction difference in lowest terms.
|
||||
*/
|
||||
public Fraction subtract(Fraction rhs) {
|
||||
return add(rhs.negate());
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduce this fraction to lowest terms. This is accomplished by dividing
|
||||
* both numerator and denominator by their greatest common divisor.
|
||||
*/
|
||||
private void reduce() {
|
||||
// reduce numerator and denominator by greatest common denominator.
|
||||
int d = MathUtils.gcd(numerator, denominator);
|
||||
if (d > 1) {
|
||||
numerator /= d;
|
||||
denominator /= d;
|
||||
}
|
||||
|
||||
// move sign to numerator.
|
||||
if (denominator < 0) {
|
||||
numerator *= -1;
|
||||
denominator *= -1;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,386 @@
|
|||
/*
|
||||
* Copyright 2005 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.commons.math.fraction;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.text.FieldPosition;
|
||||
import java.text.Format;
|
||||
import java.text.NumberFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.ParsePosition;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.apache.commons.math.ConvergenceException;
|
||||
|
||||
/**
|
||||
* Formats a Fraction number in proper format or improper format. The number
|
||||
* format for each of the whole number, numerator and, denominator can be
|
||||
* configured.
|
||||
*
|
||||
* @author Apache Software Foundation
|
||||
* @version $Revision: 1.10 $ $Date: 2004-09-20 23:45:55 -0500 (Mon, 20 Sep 2004) $
|
||||
*/
|
||||
public class FractionFormat extends Format implements Serializable {
|
||||
|
||||
/** Serializable version identifier */
|
||||
static final long serialVersionUID = -6337346779577272306L;
|
||||
|
||||
/** The format used for the denominator. */
|
||||
private NumberFormat denominatorFormat;
|
||||
|
||||
/** The format used for the numerator. */
|
||||
private NumberFormat numeratorFormat;
|
||||
|
||||
/**
|
||||
* Create an improper formatting instance with the default number format
|
||||
* for the numerator and denominator.
|
||||
*/
|
||||
public FractionFormat() {
|
||||
this(getDefaultNumberFormat());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an improper formatting instance with a custom number format for
|
||||
* both the numerator and denominator.
|
||||
* @param format the custom format for both the numerator and denominator.
|
||||
*/
|
||||
public FractionFormat(NumberFormat format) {
|
||||
this(format, (NumberFormat)format.clone());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an improper formatting instance with a custom number format for
|
||||
* the numerator and a custom number format for the denominator.
|
||||
* @param numeratorFormat the custom format for the numerator.
|
||||
* @param denominatorFormat the custom format for the denominator.
|
||||
*/
|
||||
public FractionFormat(NumberFormat numeratorFormat,
|
||||
NumberFormat denominatorFormat)
|
||||
{
|
||||
super();
|
||||
this.numeratorFormat = numeratorFormat;
|
||||
this.denominatorFormat = denominatorFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* This static method calls formatFraction() on a default instance of
|
||||
* FractionFormat.
|
||||
*
|
||||
* @param f Fraction object to format
|
||||
* @return A formatted fraction in proper form.
|
||||
*/
|
||||
public static String formatFraction(Fraction f) {
|
||||
return getImproperInstance().format(f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the set of locales for which complex formats are available. This
|
||||
* is the same set as the {@link NumberFormat} set.
|
||||
* @return available complex format locales.
|
||||
*/
|
||||
public static Locale[] getAvailableLocales() {
|
||||
return NumberFormat.getAvailableLocales();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default complex format for the current locale.
|
||||
* @return the default complex format.
|
||||
*/
|
||||
public static FractionFormat getImproperInstance() {
|
||||
return getImproperInstance(Locale.getDefault());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default complex format for the given locale.
|
||||
* @param locale the specific locale used by the format.
|
||||
* @return the complex format specific to the given locale.
|
||||
*/
|
||||
public static FractionFormat getImproperInstance(Locale locale) {
|
||||
NumberFormat f = getDefaultNumberFormat(locale);
|
||||
return new FractionFormat(f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default complex format for the current locale.
|
||||
* @return the default complex format.
|
||||
*/
|
||||
public static FractionFormat getProperInstance() {
|
||||
return getProperInstance(Locale.getDefault());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default complex format for the given locale.
|
||||
* @param locale the specific locale used by the format.
|
||||
* @return the complex format specific to the given locale.
|
||||
*/
|
||||
public static FractionFormat getProperInstance(Locale locale) {
|
||||
NumberFormat f = getDefaultNumberFormat(locale);
|
||||
return new ProperFractionFormat(f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a default number format. The default number format is based on
|
||||
* {@link NumberFormat#getInstance()} with the only customizing is the
|
||||
* maximum number of fraction digits, which is set to 2.
|
||||
* @return the default number format.
|
||||
*/
|
||||
protected static NumberFormat getDefaultNumberFormat() {
|
||||
return getDefaultNumberFormat(Locale.getDefault());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a default number format. The default number format is based on
|
||||
* {@link NumberFormat#getInstance(java.util.Locale)} with the only
|
||||
* customizing is the maximum number of fraction digits, which is set to 2.
|
||||
* @param locale the specific locale used by the format.
|
||||
* @return the default number format specific to the given locale.
|
||||
*/
|
||||
private static NumberFormat getDefaultNumberFormat(Locale locale) {
|
||||
NumberFormat nf = NumberFormat.getIntegerInstance(locale);
|
||||
return nf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a {@link Fraction} object to produce a string. The fraction is
|
||||
* output in improper format.
|
||||
*
|
||||
* @param fraction the object to format.
|
||||
* @param toAppendTo where the text is to be appended
|
||||
* @param pos On input: an alignment field, if desired. On output: the
|
||||
* offsets of the alignment field
|
||||
* @return the value passed in as toAppendTo.
|
||||
*/
|
||||
public StringBuffer format(Fraction fraction, StringBuffer toAppendTo,
|
||||
FieldPosition pos) {
|
||||
|
||||
pos.setBeginIndex(0);
|
||||
pos.setEndIndex(0);
|
||||
|
||||
getNumeratorFormat().format(fraction.getNumerator(), toAppendTo, pos);
|
||||
toAppendTo.append(" / ");
|
||||
getDenominatorFormat().format(fraction.getDenominator(), toAppendTo,
|
||||
pos);
|
||||
|
||||
return toAppendTo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a object to produce a string. <code>obj</code> must be either a
|
||||
* {@link Fraction} object or a {@link Number} object. Any other type of
|
||||
* object will result in an {@link IllegalArgumentException} being thrown.
|
||||
*
|
||||
* @param obj the object to format.
|
||||
* @param toAppendTo where the text is to be appended
|
||||
* @param pos On input: an alignment field, if desired. On output: the
|
||||
* offsets of the alignment field
|
||||
* @return the value passed in as toAppendTo.
|
||||
* @see java.text.Format#format(java.lang.Object, java.lang.StringBuffer, java.text.FieldPosition)
|
||||
* @throws IllegalArgumentException is <code>obj</code> is not a valid type.
|
||||
*/
|
||||
public StringBuffer format(Object obj, StringBuffer toAppendTo,
|
||||
FieldPosition pos)
|
||||
{
|
||||
StringBuffer ret = null;
|
||||
|
||||
if (obj instanceof Fraction) {
|
||||
ret = format( (Fraction)obj, toAppendTo, pos);
|
||||
} else if (obj instanceof Number) {
|
||||
try {
|
||||
ret = format( new Fraction(((Number)obj).doubleValue()),
|
||||
toAppendTo, pos);
|
||||
} catch (ConvergenceException ex) {
|
||||
throw new IllegalArgumentException(
|
||||
"Cannot convert given object to a fraction.");
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
"Cannot format given object as a fraction");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the denominator format.
|
||||
* @return the denominator format.
|
||||
*/
|
||||
public NumberFormat getDenominatorFormat() {
|
||||
return denominatorFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the numerator format.
|
||||
* @return the numerator format.
|
||||
*/
|
||||
public NumberFormat getNumeratorFormat() {
|
||||
return numeratorFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a string to produce a {@link Fraction} object.
|
||||
* @param source the string to parse
|
||||
* @return the parsed {@link Fraction} object.
|
||||
* @exception ParseException if the beginning of the specified string
|
||||
* cannot be parsed.
|
||||
*/
|
||||
public Fraction parse(String source) throws ParseException {
|
||||
ParsePosition parsePosition = new ParsePosition(0);
|
||||
Fraction result = parse(source, parsePosition);
|
||||
if (parsePosition.getIndex() == 0) {
|
||||
throw new ParseException("Unparseable fraction number: \"" +
|
||||
source + "\"", parsePosition.getErrorIndex());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a string to produce a {@link Fraction} object. This method
|
||||
* expects the string to be formatted as an improper fraction.
|
||||
* @param source the string to parse
|
||||
* @param pos input/ouput parsing parameter.
|
||||
* @return the parsed {@link Fraction} object.
|
||||
*/
|
||||
public Fraction parse(String source, ParsePosition pos) {
|
||||
int initialIndex = pos.getIndex();
|
||||
|
||||
// parse whitespace
|
||||
parseAndIgnoreWhitespace(source, pos);
|
||||
|
||||
// parse numerator
|
||||
Number num = getNumeratorFormat().parse(source, pos);
|
||||
if (num == null) {
|
||||
// invalid integer number
|
||||
// set index back to initial, error index should already be set
|
||||
// character examined.
|
||||
pos.setIndex(initialIndex);
|
||||
return null;
|
||||
}
|
||||
|
||||
// parse '/'
|
||||
int startIndex = pos.getIndex();
|
||||
char c = parseNextCharacter(source, pos);
|
||||
switch (c) {
|
||||
case 0 :
|
||||
// no '/'
|
||||
// return num as a fraction
|
||||
return new Fraction(num.intValue(), 1);
|
||||
case '/' :
|
||||
// found '/', continue parsing denominator
|
||||
break;
|
||||
default :
|
||||
// invalid '/'
|
||||
// set index back to initial, error index should be the last
|
||||
// character examined.
|
||||
pos.setIndex(initialIndex);
|
||||
pos.setErrorIndex(startIndex);
|
||||
return null;
|
||||
}
|
||||
|
||||
// parse whitespace
|
||||
parseAndIgnoreWhitespace(source, pos);
|
||||
|
||||
// parse denominator
|
||||
Number den = getDenominatorFormat().parse(source, pos);
|
||||
if (den == null) {
|
||||
// invalid integer number
|
||||
// set index back to initial, error index should already be set
|
||||
// character examined.
|
||||
pos.setIndex(initialIndex);
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Fraction(num.intValue(), den.intValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a string to produce a object.
|
||||
* @param source the string to parse
|
||||
* @param pos input/ouput parsing parameter.
|
||||
* @return the parsed object.
|
||||
* @see java.text.Format#parseObject(java.lang.String, java.text.ParsePosition)
|
||||
*/
|
||||
public Object parseObject(String source, ParsePosition pos) {
|
||||
return parse(source, pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify the denominator format.
|
||||
* @param format the new denominator format value.
|
||||
* @throws IllegalArgumentException if <code>format</code> is
|
||||
* <code>null</code>.
|
||||
*/
|
||||
public void setDenominatorFormat(NumberFormat format) {
|
||||
if (format == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"denominator format can not be null.");
|
||||
}
|
||||
this.denominatorFormat = format;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify the numerator format.
|
||||
* @param format the new numerator format value.
|
||||
* @throws IllegalArgumentException if <code>format</code> is
|
||||
* <code>null</code>.
|
||||
*/
|
||||
public void setNumeratorFormat(NumberFormat format) {
|
||||
if (format == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"numerator format can not be null.");
|
||||
}
|
||||
this.numeratorFormat = format;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses <code>source</code> until a non-whitespace character is found.
|
||||
* @param source the string to parse
|
||||
* @param pos input/ouput parsing parameter. On output, <code>pos</code>
|
||||
* holds the index of the next non-whitespace character.
|
||||
*/
|
||||
protected static void parseAndIgnoreWhitespace(
|
||||
String source, ParsePosition pos)
|
||||
{
|
||||
parseNextCharacter(source, pos);
|
||||
pos.setIndex(pos.getIndex() - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses <code>source</code> until a non-whitespace character is found.
|
||||
* @param source the string to parse
|
||||
* @param pos input/ouput parsing parameter.
|
||||
* @return the first non-whitespace character.
|
||||
*/
|
||||
protected static char parseNextCharacter(String source, ParsePosition pos) {
|
||||
int index = pos.getIndex();
|
||||
int n = source.length();
|
||||
char ret = 0;
|
||||
|
||||
if (index < n) {
|
||||
char c;
|
||||
do {
|
||||
c = source.charAt(index++);
|
||||
} while (Character.isWhitespace(c) && index < n);
|
||||
pos.setIndex(index);
|
||||
|
||||
if (index < n) {
|
||||
ret = c;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,208 @@
|
|||
/*
|
||||
* Copyright 2005 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.math.fraction;
|
||||
|
||||
import java.text.FieldPosition;
|
||||
import java.text.NumberFormat;
|
||||
import java.text.ParsePosition;
|
||||
|
||||
import org.apache.commons.math.util.MathUtils;
|
||||
|
||||
/**
|
||||
* Formats a Fraction number in proper format. The number format for each of
|
||||
* the whole number, numerator and, denominator can be configured.
|
||||
*
|
||||
* @author Apache Software Foundation
|
||||
* @version $Revision: $ $Date: $
|
||||
*/
|
||||
public class ProperFractionFormat extends FractionFormat {
|
||||
|
||||
/** Serializable version identifier */
|
||||
static final long serialVersionUID = -6337346779577272307L;
|
||||
|
||||
/** The format used for the whole number. */
|
||||
private NumberFormat wholeFormat;
|
||||
|
||||
/**
|
||||
* Create a proper formatting instance with the default number format for
|
||||
* the whole, numerator, and denominator.
|
||||
*/
|
||||
public ProperFractionFormat() {
|
||||
this(getDefaultNumberFormat());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a proper formatting instance with a custom number format for the
|
||||
* whole, numerator, and denominator.
|
||||
* @param format the custom format for the whole, numerator, and
|
||||
* denominator.
|
||||
*/
|
||||
public ProperFractionFormat(NumberFormat format) {
|
||||
this(format, (NumberFormat)format.clone(), (NumberFormat)format.clone());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a proper formatting instance with a custom number format for each
|
||||
* of the whole, numerator, and denominator.
|
||||
* @param wholeFormat the custom format for the whole.
|
||||
* @param numeratorFormat the custom format for the numerator.
|
||||
* @param denominatorFormat the custom format for the denominator.
|
||||
*/
|
||||
public ProperFractionFormat(NumberFormat wholeFormat,
|
||||
NumberFormat numeratorFormat,
|
||||
NumberFormat denominatorFormat)
|
||||
{
|
||||
super(numeratorFormat, denominatorFormat);
|
||||
setWholeFormat(wholeFormat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a {@link Fraction} object to produce a string. The fraction
|
||||
* is output in proper format.
|
||||
*
|
||||
* @param fraction the object to format.
|
||||
* @param toAppendTo where the text is to be appended
|
||||
* @param pos On input: an alignment field, if desired. On output: the
|
||||
* offsets of the alignment field
|
||||
* @return the value passed in as toAppendTo.
|
||||
*/
|
||||
public StringBuffer format(Fraction fraction, StringBuffer toAppendTo,
|
||||
FieldPosition pos) {
|
||||
|
||||
pos.setBeginIndex(0);
|
||||
pos.setEndIndex(0);
|
||||
|
||||
int num = fraction.getNumerator();
|
||||
int den = fraction.getDenominator();
|
||||
int whole = num / den;
|
||||
num = num % den;
|
||||
|
||||
if (whole != 0) {
|
||||
getWholeFormat().format(whole, toAppendTo, pos);
|
||||
toAppendTo.append(' ');
|
||||
num = Math.abs(num);
|
||||
}
|
||||
getNumeratorFormat().format(num, toAppendTo, pos);
|
||||
toAppendTo.append(" / ");
|
||||
getDenominatorFormat().format(den, toAppendTo,
|
||||
pos);
|
||||
|
||||
return toAppendTo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the whole format.
|
||||
* @return the whole format.
|
||||
*/
|
||||
public NumberFormat getWholeFormat() {
|
||||
return wholeFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a string to produce a {@link Fraction} object. This method
|
||||
* expects the string to be formatted as a proper fraction.
|
||||
* @param source the string to parse
|
||||
* @param pos input/ouput parsing parameter.
|
||||
* @return the parsed {@link Fraction} object.
|
||||
*/
|
||||
public Fraction parse(String source, ParsePosition pos) {
|
||||
// try to parse improper fraction
|
||||
Fraction ret = super.parse(source, pos);
|
||||
if (ret != null) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
int initialIndex = pos.getIndex();
|
||||
|
||||
// parse whitespace
|
||||
parseAndIgnoreWhitespace(source, pos);
|
||||
|
||||
// parse whole
|
||||
Number whole = getWholeFormat().parse(source, pos);
|
||||
if (whole == null) {
|
||||
// invalid integer number
|
||||
// set index back to initial, error index should already be set
|
||||
// character examined.
|
||||
pos.setIndex(initialIndex);
|
||||
return null;
|
||||
}
|
||||
|
||||
// parse whitespace
|
||||
parseAndIgnoreWhitespace(source, pos);
|
||||
|
||||
// parse numerator
|
||||
Number num = getNumeratorFormat().parse(source, pos);
|
||||
if (num == null) {
|
||||
// invalid integer number
|
||||
// set index back to initial, error index should already be set
|
||||
// character examined.
|
||||
pos.setIndex(initialIndex);
|
||||
return null;
|
||||
}
|
||||
|
||||
// parse '/'
|
||||
int startIndex = pos.getIndex();
|
||||
char c = parseNextCharacter(source, pos);
|
||||
switch (c) {
|
||||
case 0 :
|
||||
// no '/'
|
||||
// return num as a fraction
|
||||
return new Fraction(num.intValue(), 1);
|
||||
case '/' :
|
||||
// found '/', continue parsing denominator
|
||||
break;
|
||||
default :
|
||||
// invalid '/'
|
||||
// set index back to initial, error index should be the last
|
||||
// character examined.
|
||||
pos.setIndex(initialIndex);
|
||||
pos.setErrorIndex(startIndex);
|
||||
return null;
|
||||
}
|
||||
|
||||
// parse whitespace
|
||||
parseAndIgnoreWhitespace(source, pos);
|
||||
|
||||
// parse denominator
|
||||
Number den = getDenominatorFormat().parse(source, pos);
|
||||
if (den == null) {
|
||||
// invalid integer number
|
||||
// set index back to initial, error index should already be set
|
||||
// character examined.
|
||||
pos.setIndex(initialIndex);
|
||||
return null;
|
||||
}
|
||||
|
||||
int w = whole.intValue();
|
||||
int n = num.intValue();
|
||||
int d = den.intValue();
|
||||
return new Fraction(((Math.abs(w) * d) + n) * MathUtils.sign(w), d);
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify the whole format.
|
||||
* @param format The new whole format value.
|
||||
* @throws IllegalArgumentException if <code>format</code> is
|
||||
* <code>null</code>.
|
||||
*/
|
||||
public void setWholeFormat(NumberFormat format) {
|
||||
if (format == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"whole format can not be null.");
|
||||
}
|
||||
this.wholeFormat = format;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
<html>
|
||||
<!--
|
||||
Copyright 2005 The Apache Software Foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<!-- $Revision: 1.1 $ $Date: 2004/04/26 18:28:16 $ -->
|
||||
<body>
|
||||
Fraction number type and fraction number formatting.
|
||||
</body>
|
||||
</html>
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2003-2004 The Apache Software Foundation.
|
||||
* Copyright 2003-2005 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -19,7 +19,7 @@ package org.apache.commons.math.util;
|
|||
/**
|
||||
* Some useful additions to the built-in functions in {@link Math}.
|
||||
*
|
||||
* @version $Revision: 1.20 $ $Date: 2004/10/14 04:01:04 $
|
||||
* @version $Revision: 1.20 $ $Date$
|
||||
*/
|
||||
public final class MathUtils {
|
||||
|
||||
|
@ -468,4 +468,43 @@ public final class MathUtils {
|
|||
public static boolean equals(double x, double y) {
|
||||
return ((Double.isNaN(x) && Double.isNaN(y)) || x == y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the least common multiple between two integer values.
|
||||
* @param a the first integer value.
|
||||
* @param b the second integer value.
|
||||
* @return the least common multiple between a and b.
|
||||
*/
|
||||
public static int lcm(int a, int b) {
|
||||
return Math.abs(a / gcd(a, b) * b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the greatest common divisor between two integer values.
|
||||
* @param a the first integer value.
|
||||
* @param b the second integer value.
|
||||
* @return the greatest common divisor between a and b.
|
||||
*/
|
||||
public static int gcd(int a, int b) {
|
||||
int ret;
|
||||
|
||||
if (a == 0) {
|
||||
ret = Math.abs(b);
|
||||
} else if (b == 0) {
|
||||
ret = Math.abs(a);
|
||||
} else if (a < 0) {
|
||||
ret = gcd(-a, b);
|
||||
} else if (b < 0) {
|
||||
ret = gcd(a, -b);
|
||||
} else {
|
||||
int r = 0;
|
||||
while(b > 0){
|
||||
r = a % b;
|
||||
a = b;
|
||||
b = r;
|
||||
}
|
||||
ret = a;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,176 @@
|
|||
/*
|
||||
* Copyright 2004 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.commons.math.fraction;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.Locale;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class FractionFormatTest extends TestCase {
|
||||
|
||||
FractionFormat properFormat = null;
|
||||
FractionFormat improperFormat = null;
|
||||
|
||||
protected Locale getLocale() {
|
||||
return Locale.getDefault();
|
||||
}
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
properFormat = FractionFormat.getProperInstance(getLocale());
|
||||
improperFormat = FractionFormat.getImproperInstance(getLocale());
|
||||
}
|
||||
|
||||
public void testFormat() {
|
||||
Fraction c = new Fraction(1, 2);
|
||||
String expected = "1 / 2";
|
||||
|
||||
String actual = properFormat.format(c);
|
||||
assertEquals(expected, actual);
|
||||
|
||||
actual = improperFormat.format(c);
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
|
||||
public void testFormatNegative() {
|
||||
Fraction c = new Fraction(-1, 2);
|
||||
String expected = "-1 / 2";
|
||||
|
||||
String actual = properFormat.format(c);
|
||||
assertEquals(expected, actual);
|
||||
|
||||
actual = improperFormat.format(c);
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
|
||||
public void testFormatZero() {
|
||||
Fraction c = new Fraction(0, 1);
|
||||
String expected = "0 / 1";
|
||||
|
||||
String actual = properFormat.format(c);
|
||||
assertEquals(expected, actual);
|
||||
|
||||
actual = improperFormat.format(c);
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
|
||||
public void testFormatImproper() {
|
||||
Fraction c = new Fraction(5, 3);
|
||||
|
||||
String actual = properFormat.format(c);
|
||||
assertEquals("1 2 / 3", actual);
|
||||
|
||||
actual = improperFormat.format(c);
|
||||
assertEquals("5 / 3", actual);
|
||||
}
|
||||
|
||||
public void testFormatImproperNegative() {
|
||||
Fraction c = new Fraction(-5, 3);
|
||||
|
||||
String actual = properFormat.format(c);
|
||||
assertEquals("-1 2 / 3", actual);
|
||||
|
||||
actual = improperFormat.format(c);
|
||||
assertEquals("-5 / 3", actual);
|
||||
}
|
||||
|
||||
public void testParse() {
|
||||
String source = "1 / 2";
|
||||
|
||||
try {
|
||||
Fraction c = properFormat.parse(source);
|
||||
assertNotNull(c);
|
||||
assertEquals(1, c.getNumerator());
|
||||
assertEquals(2, c.getDenominator());
|
||||
|
||||
c = improperFormat.parse(source);
|
||||
assertNotNull(c);
|
||||
assertEquals(1, c.getNumerator());
|
||||
assertEquals(2, c.getDenominator());
|
||||
} catch (ParseException ex) {
|
||||
fail(ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testParseNegative() {
|
||||
|
||||
try {
|
||||
String source = "-1 / 2";
|
||||
Fraction c = properFormat.parse(source);
|
||||
assertNotNull(c);
|
||||
assertEquals(-1, c.getNumerator());
|
||||
assertEquals(2, c.getDenominator());
|
||||
|
||||
c = improperFormat.parse(source);
|
||||
assertNotNull(c);
|
||||
assertEquals(-1, c.getNumerator());
|
||||
assertEquals(2, c.getDenominator());
|
||||
|
||||
source = "1 / -2";
|
||||
c = properFormat.parse(source);
|
||||
assertNotNull(c);
|
||||
assertEquals(-1, c.getNumerator());
|
||||
assertEquals(2, c.getDenominator());
|
||||
|
||||
c = improperFormat.parse(source);
|
||||
assertNotNull(c);
|
||||
assertEquals(-1, c.getNumerator());
|
||||
assertEquals(2, c.getDenominator());
|
||||
} catch (ParseException ex) {
|
||||
fail(ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testParseProper() {
|
||||
String source = "1 2 / 3";
|
||||
|
||||
try {
|
||||
Fraction c = properFormat.parse(source);
|
||||
assertNotNull(c);
|
||||
assertEquals(5, c.getNumerator());
|
||||
assertEquals(3, c.getDenominator());
|
||||
} catch (ParseException ex) {
|
||||
fail(ex.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
improperFormat.parse(source);
|
||||
fail("invalid improper fraction.");
|
||||
} catch (ParseException ex) {
|
||||
// success
|
||||
}
|
||||
}
|
||||
|
||||
public void testParseProperNegative() {
|
||||
String source = "-1 2 / 3";
|
||||
try {
|
||||
Fraction c = properFormat.parse(source);
|
||||
assertNotNull(c);
|
||||
assertEquals(-5, c.getNumerator());
|
||||
assertEquals(3, c.getDenominator());
|
||||
} catch (ParseException ex) {
|
||||
fail(ex.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
improperFormat.parse(source);
|
||||
fail("invalid improper fraction.");
|
||||
} catch (ParseException ex) {
|
||||
// success
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Copyright 2005 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.math.fraction;
|
||||
|
||||
import org.apache.commons.math.ConvergenceException;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* @version $Revision: $ $Date: $
|
||||
*/
|
||||
public class FractionTest extends TestCase {
|
||||
|
||||
private void assertFraction(int expectedNumerator, int expectedDenominator, Fraction actual) {
|
||||
assertEquals(expectedNumerator, actual.getNumerator());
|
||||
assertEquals(expectedDenominator, actual.getDenominator());
|
||||
}
|
||||
|
||||
public void testConstructor() {
|
||||
assertFraction(0, 1, new Fraction(0, 1));
|
||||
assertFraction(0, 1, new Fraction(0, 2));
|
||||
assertFraction(0, 1, new Fraction(0, -1));
|
||||
assertFraction(1, 2, new Fraction(1, 2));
|
||||
assertFraction(1, 2, new Fraction(2, 4));
|
||||
assertFraction(-1, 2, new Fraction(-1, 2));
|
||||
assertFraction(-1, 2, new Fraction(1, -2));
|
||||
assertFraction(-1, 2, new Fraction(-2, 4));
|
||||
assertFraction(-1, 2, new Fraction(2, -4));
|
||||
}
|
||||
|
||||
public void testConstructorDouble() {
|
||||
try {
|
||||
assertFraction(1, 2, new Fraction(0.5));
|
||||
assertFraction(1, 3, new Fraction(1.0 / 3.0));
|
||||
assertFraction(17, 100, new Fraction(17.0 / 100.0));
|
||||
assertFraction(317, 100, new Fraction(317.0 / 100.0));
|
||||
assertFraction(-1, 2, new Fraction(-0.5));
|
||||
assertFraction(-1, 3, new Fraction(-1.0 / 3.0));
|
||||
assertFraction(-17, 100, new Fraction(17.0 / -100.0));
|
||||
assertFraction(-317, 100, new Fraction(-317.0 / 100.0));
|
||||
} catch (ConvergenceException ex) {
|
||||
fail(ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testAbs() {
|
||||
Fraction a = new Fraction(10, 21);
|
||||
Fraction b = new Fraction(-10, 21);
|
||||
Fraction c = new Fraction(10, -21);
|
||||
|
||||
assertFraction(10, 21, a.abs());
|
||||
assertFraction(10, 21, b.abs());
|
||||
assertFraction(10, 21, c.abs());
|
||||
}
|
||||
|
||||
public void testAdd() {
|
||||
Fraction a = new Fraction(1, 2);
|
||||
Fraction b = new Fraction(2, 3);
|
||||
|
||||
assertFraction(1, 1, a.add(a));
|
||||
assertFraction(7, 6, a.add(b));
|
||||
assertFraction(7, 6, b.add(a));
|
||||
assertFraction(4, 3, b.add(b));
|
||||
}
|
||||
|
||||
public void testDivide() {
|
||||
Fraction a = new Fraction(1, 2);
|
||||
Fraction b = new Fraction(2, 3);
|
||||
|
||||
assertFraction(1, 1, a.divide(a));
|
||||
assertFraction(3, 4, a.divide(b));
|
||||
assertFraction(4, 3, b.divide(a));
|
||||
assertFraction(1, 1, b.divide(b));
|
||||
}
|
||||
|
||||
public void testMultiply() {
|
||||
Fraction a = new Fraction(1, 2);
|
||||
Fraction b = new Fraction(2, 3);
|
||||
|
||||
assertFraction(1, 4, a.multiply(a));
|
||||
assertFraction(1, 3, a.multiply(b));
|
||||
assertFraction(1, 3, b.multiply(a));
|
||||
assertFraction(4, 9, b.multiply(b));
|
||||
}
|
||||
|
||||
public void testSubtract() {
|
||||
Fraction a = new Fraction(1, 2);
|
||||
Fraction b = new Fraction(2, 3);
|
||||
|
||||
assertFraction(0, 1, a.subtract(a));
|
||||
assertFraction(-1, 6, a.subtract(b));
|
||||
assertFraction(1, 6, b.subtract(a));
|
||||
assertFraction(0, 1, b.subtract(b));
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2003-2004 The Apache Software Foundation.
|
||||
* Copyright 2003-2005 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -22,9 +22,8 @@ import junit.framework.TestSuite;
|
|||
/**
|
||||
* Test cases for the MathUtils class.
|
||||
*
|
||||
* @version $Revision: 1.15 $ $Date: 2004/10/14 04:01:04 $
|
||||
* @version $Revision: 1.15 $ $Date$
|
||||
*/
|
||||
|
||||
public final class MathUtilsTest extends TestCase {
|
||||
|
||||
public MathUtilsTest(String name) {
|
||||
|
@ -389,4 +388,42 @@ public final class MathUtilsTest extends TestCase {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void testGcd() {
|
||||
int a = 30;
|
||||
int b = 50;
|
||||
int c = 77;
|
||||
|
||||
assertEquals(0, MathUtils.gcd(0, 0));
|
||||
|
||||
assertEquals(b, MathUtils.gcd( 0, b));
|
||||
assertEquals(a, MathUtils.gcd( a, 0));
|
||||
assertEquals(b, MathUtils.gcd( 0, -b));
|
||||
assertEquals(a, MathUtils.gcd(-a, 0));
|
||||
|
||||
assertEquals(10, MathUtils.gcd( a, b));
|
||||
assertEquals(10, MathUtils.gcd(-a, b));
|
||||
assertEquals(10, MathUtils.gcd( a, -b));
|
||||
assertEquals(10, MathUtils.gcd(-a, -b));
|
||||
|
||||
assertEquals(1, MathUtils.gcd( a, c));
|
||||
assertEquals(1, MathUtils.gcd(-a, c));
|
||||
assertEquals(1, MathUtils.gcd( a, -c));
|
||||
assertEquals(1, MathUtils.gcd(-a, -c));
|
||||
}
|
||||
|
||||
public void testLcm() {
|
||||
int a = 30;
|
||||
int b = 50;
|
||||
int c = 77;
|
||||
|
||||
assertEquals(0, MathUtils.lcm(0, b));
|
||||
assertEquals(0, MathUtils.lcm(a, 0));
|
||||
assertEquals(b, MathUtils.lcm(1, b));
|
||||
assertEquals(a, MathUtils.lcm(a, 1));
|
||||
assertEquals(150, MathUtils.lcm(a, b));
|
||||
assertEquals(150, MathUtils.lcm(-a, b));
|
||||
assertEquals(150, MathUtils.lcm(a, -b));
|
||||
assertEquals(2310, MathUtils.lcm(a, c));
|
||||
}
|
||||
}
|
|
@ -37,6 +37,14 @@ The <action> type attribute can be add,update,fix,remove.
|
|||
<title>Commons Math Release Notes</title>
|
||||
</properties>
|
||||
<body>
|
||||
<release version="1.1" date="In Development"
|
||||
description="Jakarta Commons Math 1.1 - Development">
|
||||
<action dev="brentworden" type="add" due-to="C. Scott Ananian">
|
||||
Added Fraction class based on commons-lang implementation. With the
|
||||
fraction class, FractionFormat and ProperFractionFormat classes were
|
||||
added to provide fraction formatting and parsing.
|
||||
</action>
|
||||
</release>
|
||||
<release version="1.0" date="2004-12-06"
|
||||
description="Jakarta Commons Math 1.0 - General Availability Release">
|
||||
<action dev="psteitz" type="fix" due-to="Hans van der Heijden" issue="32531">
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
<item name="Utilities" href="/userguide/utilities.html"/>
|
||||
<item name="Complex Numbers" href="/userguide/complex.html"/>
|
||||
<item name="Distributions" href="/userguide/distribution.html"/>
|
||||
<item name="Fractions" href="/userguide/fraction.html"/>
|
||||
</menu>
|
||||
|
||||
&common-menus;
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
-->
|
||||
|
||||
<?xml-stylesheet type="text/xsl" href="xdoc.xsl"?>
|
||||
<!-- $Revision: 1.24 $ $Date: 2004/07/25 15:13:47 $ -->
|
||||
<!-- $Revision: 1.24 $ $Date$ -->
|
||||
<document>
|
||||
<properties>
|
||||
<title>Tasks: To Do</title>
|
||||
|
@ -79,12 +79,6 @@
|
|||
<li>Sparse matrices</li>
|
||||
</ul>
|
||||
</dd>
|
||||
<dt>Math</dt>
|
||||
<dd>
|
||||
<ul>
|
||||
<li>Rational Number (or Fraction) class</li>
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>
|
||||
</subsection>
|
||||
</section>
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<!--
|
||||
Copyright 2005 The Apache Software Foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<?xml-stylesheet type="text/xsl" href="./xdoc.xsl"?>
|
||||
<!-- $Revision: 1.4 $ $Date: 2004-11-07 19:03:43 -0600 (Sun, 07 Nov 2004) $ -->
|
||||
<document url="stat.html">
|
||||
<properties>
|
||||
<title>The Commons Math User Guide - Fractions</title>
|
||||
</properties>
|
||||
<body>
|
||||
<section name="9 Fractions">
|
||||
<subsection name="9.1 Overview" href="overview">
|
||||
<p>
|
||||
The fraction packages provides a fraction number type as well as
|
||||
fraction number formatting.
|
||||
</p>
|
||||
</subsection>
|
||||
<subsection name="9.2 Fraction Numbers" href="fraction">
|
||||
<p>
|
||||
<a href="../apidocs/org/apache/commons/math/fraction/Fraction.html">
|
||||
org.apache.commons.math.fraction.Fraction</a> provides a fraction number
|
||||
type that forms the basis for the fraction functionality found in
|
||||
commons-math.
|
||||
</p>
|
||||
<p>
|
||||
To create a fraction number, simply call the constructor passing in two
|
||||
integer arguments, the first being the numerator of the fraction and the second being the denominator:
|
||||
<source>Fraction f = new Fraction(1, 3); // 1 / 3</source>
|
||||
</p>
|
||||
<p>
|
||||
Of special note with fraction construction, when a fraction is created it is always reduced to lowest terms.
|
||||
</p>
|
||||
<p>
|
||||
The <code>Fraction</code> class provides many unary and binary
|
||||
fraction operations. These operations provide the means to add,
|
||||
subtract, multiple and, divide fractions along with other functions similar to the real number functions found in
|
||||
<code>java.math.BigDecimal</code>:
|
||||
<source>Fraction lhs = new Fraction(1, 3);
|
||||
Fraction rhs = new Fraction(2, 5);
|
||||
|
||||
Fraction answer = lhs.add(rhs); // add two fractions
|
||||
answer = lhs.subtract(rhs); // subtract two fractions
|
||||
answer = lhs.abs(); // absolute value
|
||||
answer = lhs.reciprocal(); // reciprocal of lhs</source>
|
||||
</p>
|
||||
<p>
|
||||
Like fraction construction, for each of the fraction functions, the resulting fraction is reduced to lowest terms.
|
||||
</p>
|
||||
</subsection>
|
||||
<subsection name="9.3 Fraction Formatting and Parsing" href="formatting">
|
||||
<p>
|
||||
<code>Fraction</code> instances can be converted to and from strings
|
||||
using the<a href="../apidocs/org/apache/commons/math/fraction/FractionFormat.html">
|
||||
org.apache.commons.math.fraction.FractionFormat</a> class.
|
||||
<code>FractionFormat</code> is a <code>java.text.Format</code>
|
||||
extension and, as such, is used like other formatting objects (e.g.
|
||||
<code>java.text.SimpleDateFormat</code>):
|
||||
<source>FractionFormat format = new FractionFormat(); // default format
|
||||
Fraction f = new Fraction(2, 4);
|
||||
String s = format.format(f); // s contains "1 / 2", note the reduced fraction</source>
|
||||
</p>
|
||||
<p>
|
||||
To customize the formatting output, one or two
|
||||
<code>java.text.NumberFormat</code> instances can be used to construct
|
||||
a <code>FractionFormat</code>. These number formats control the
|
||||
formatting of the numerator and denominator of the fraction:
|
||||
<source>NumberFormat nf = NumberFormat.getInstance(Locale.FRANCE);
|
||||
// create fraction format with custom number format
|
||||
// when one number format is used, both numerator and
|
||||
// denominator are formatted the same
|
||||
FractionFormat format = new FractionFormat(nf);
|
||||
Fraction f = new Fraction(2000, 3333);
|
||||
String s = format.format(c); // s contains "2.000 / 3.333"
|
||||
|
||||
NumberFormat nf2 = NumberFormat.getInstance(Locale.US);
|
||||
// create fraction format with custom number formats
|
||||
format = new FractionFormat(nf, nf2);
|
||||
s = format.format(f); // s contains "2.000 / 3,333"</source>
|
||||
</p>
|
||||
<p>
|
||||
Formatting's inverse operation, parsing, can also be performed by
|
||||
<code>FractionFormat</code>. To parse a fraction from a string,
|
||||
simply call the <code>parse</code> method:
|
||||
<source>FractionFormat ff = new FractionFormat();
|
||||
Fraction f = ff.parse("-10 / 21");</source>
|
||||
</p>
|
||||
</subsection>
|
||||
</section>
|
||||
</body>
|
||||
</document>
|
|
@ -17,7 +17,7 @@
|
|||
-->
|
||||
|
||||
<?xml-stylesheet type="text/xsl" href="./xdoc.xsl"?>
|
||||
<!-- $Revision: 1.13 $ $Date: 2004/11/09 02:26:55 $ -->
|
||||
<!-- $Revision: 1.13 $ $Date$ -->
|
||||
<document url="index.html">
|
||||
<properties>
|
||||
<title>The Commons Math User Guide - Table of Contents</title>
|
||||
|
@ -92,6 +92,12 @@
|
|||
<li><a href="distribution.html#distributions">8.2 Distribution Framework</a></li>
|
||||
<li><a href="distribution.html#userdefined">8.3 User Defined Distributions</a></li>
|
||||
</ul></li>
|
||||
<li><a href="fraction.html">9. Fractions</a>
|
||||
<ul>
|
||||
<li><a href="fraction.html#overview">9.1 Overview</a></li>
|
||||
<li><a href="fraction.html#fraction">9.2 Fraction Numbers</a></li>
|
||||
<li><a href="fraction.html#formatting">9.3 Fraction Formatting and Parsing</a></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
|
|
Loading…
Reference in New Issue