[MATH-996] Fix creation of Fraction/BigFraction objects in maxDenominator mode when the value is close to an actual fraction.
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1519204 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
d7fd760eb8
commit
86545dab3e
3
pom.xml
3
pom.xml
|
@ -132,6 +132,9 @@
|
|||
<contributor>
|
||||
<name>Eldar Agalarov</name>
|
||||
</contributor>
|
||||
<contributor>
|
||||
<name>Tim Allison</name>
|
||||
</contributor>
|
||||
<contributor>
|
||||
<name>C. Scott Ananian</name>
|
||||
</contributor>
|
||||
|
|
|
@ -51,6 +51,11 @@ If the output is not quite correct, check for invisible trailing spaces!
|
|||
</properties>
|
||||
<body>
|
||||
<release version="x.y" date="TBD" description="TBD">
|
||||
<action dev="tn" type=fix issue="MATH-996" due-to="Tim Allison">
|
||||
Creating a "Fraction" or "BigFraction" object with a maxDenominator parameter
|
||||
does not throw a "FractionConversionException" in case the value is very close
|
||||
to fraction.
|
||||
</action>
|
||||
<action dev="tn" type="add" issue="MATH-1028" due-to="Thorsten Schäfer">
|
||||
Added new distance metric "EarthMoversDistance".
|
||||
</action>
|
||||
|
|
|
@ -301,6 +301,11 @@ public class BigFraction
|
|||
p2 = (a1 * p1) + p0;
|
||||
q2 = (a1 * q1) + q0;
|
||||
if ((p2 > overflow) || (q2 > overflow)) {
|
||||
// in maxDenominator mode, if the last fraction was very close to the actual value
|
||||
// q2 may overflow in the next iteration; in this case return the last one.
|
||||
if (epsilon == 0.0 && FastMath.abs(q1) < maxDenominator) {
|
||||
break;
|
||||
}
|
||||
throw new FractionConversionException(value, p2, q2);
|
||||
}
|
||||
|
||||
|
|
|
@ -83,6 +83,9 @@ public class Fraction
|
|||
/** Serializable version identifier */
|
||||
private static final long serialVersionUID = 3698073679419233275L;
|
||||
|
||||
/** The default epsilon used for convergence. */
|
||||
private static final double DEFAULT_EPSILON = 1e-5;
|
||||
|
||||
/** The denominator. */
|
||||
private final int denominator;
|
||||
|
||||
|
@ -96,7 +99,7 @@ public class Fraction
|
|||
* converge.
|
||||
*/
|
||||
public Fraction(double value) throws FractionConversionException {
|
||||
this(value, 1.0e-5, 100);
|
||||
this(value, DEFAULT_EPSILON, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -182,8 +185,7 @@ public class Fraction
|
|||
throw new FractionConversionException(value, a0, 1l);
|
||||
}
|
||||
|
||||
// check for (almost) integer arguments, which should not go
|
||||
// to iterations.
|
||||
// check for (almost) integer arguments, which should not go to iterations.
|
||||
if (FastMath.abs(a0 - value) < epsilon) {
|
||||
this.numerator = (int) a0;
|
||||
this.denominator = 1;
|
||||
|
@ -206,7 +208,13 @@ public class Fraction
|
|||
long a1 = (long)FastMath.floor(r1);
|
||||
p2 = (a1 * p1) + p0;
|
||||
q2 = (a1 * q1) + q0;
|
||||
|
||||
if ((FastMath.abs(p2) > overflow) || (FastMath.abs(q2) > overflow)) {
|
||||
// in maxDenominator mode, if the last fraction was very close to the actual value
|
||||
// q2 may overflow in the next iteration; in this case return the last one.
|
||||
if (epsilon == 0.0 && FastMath.abs(q1) < maxDenominator) {
|
||||
break;
|
||||
}
|
||||
throw new FractionConversionException(value, p2, q2);
|
||||
}
|
||||
|
||||
|
|
|
@ -154,6 +154,9 @@ public class BigFractionTest {
|
|||
assertFraction(8, 13, new BigFraction(0.6152, 99));
|
||||
assertFraction(510, 829, new BigFraction(0.6152, 999));
|
||||
assertFraction(769, 1250, new BigFraction(0.6152, 9999));
|
||||
|
||||
// MATH-996
|
||||
assertFraction(1, 2, new BigFraction(0.5000000001, 10));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -129,6 +129,9 @@ public class FractionTest {
|
|||
assertFraction(8, 13, new Fraction(0.6152, 99));
|
||||
assertFraction(510, 829, new Fraction(0.6152, 999));
|
||||
assertFraction(769, 1250, new Fraction(0.6152, 9999));
|
||||
|
||||
// MATH-996
|
||||
assertFraction(1, 2, new Fraction(0.5000000001, 10));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -141,7 +144,9 @@ public class FractionTest {
|
|||
|
||||
private void checkIntegerOverflow(double a) {
|
||||
try {
|
||||
new Fraction(a, 1.0e-12, 1000);
|
||||
@SuppressWarnings("unused")
|
||||
Fraction f = new Fraction(a, 1.0e-12, 1000);
|
||||
//System.out.println(f.getNumerator() + "/" + f.getDenominator());
|
||||
Assert.fail("an exception should have been thrown");
|
||||
} catch (ConvergenceException ce) {
|
||||
// expected behavior
|
||||
|
|
Loading…
Reference in New Issue