diff --git a/src/java/org/apache/commons/math/fraction/Fraction.java b/src/java/org/apache/commons/math/fraction/Fraction.java index fa396fbaa..d6d2f181f 100644 --- a/src/java/org/apache/commons/math/fraction/Fraction.java +++ b/src/java/org/apache/commons/math/fraction/Fraction.java @@ -256,20 +256,9 @@ public class Fraction extends Number implements Comparable { * than object, 0 if they are equal. */ public int compareTo(Fraction object) { - int ret = 0; - - if (this != object) { - double first = doubleValue(); - double second = object.doubleValue(); - - if (first < second) { - ret = -1; - } else if (first > second) { - ret = 1; - } - } - - return ret; + long nOd = ((long) numerator) * object.denominator; + long dOn = ((long) denominator) * object.numerator; + return (nOd < dOn) ? -1 : ((nOd > dOn) ? +1 : 0); } /** diff --git a/src/site/xdoc/changes.xml b/src/site/xdoc/changes.xml index 5abf3b01d..6569346bf 100644 --- a/src/site/xdoc/changes.xml +++ b/src/site/xdoc/changes.xml @@ -39,6 +39,10 @@ The type attribute can be add,update,fix,remove. + + Fixed a comparison error when two different fractions evaluate to the + same double due to limited precision. + Added a BigFraction class that does not overflow when big numerators or denominators are used. diff --git a/src/test/org/apache/commons/math/fraction/FractionTest.java b/src/test/org/apache/commons/math/fraction/FractionTest.java index 7eb2bbdec..3644b0e23 100644 --- a/src/test/org/apache/commons/math/fraction/FractionTest.java +++ b/src/test/org/apache/commons/math/fraction/FractionTest.java @@ -169,6 +169,15 @@ public class FractionTest extends TestCase { assertEquals(0, first.compareTo(third)); assertEquals(1, first.compareTo(second)); assertEquals(-1, second.compareTo(first)); + + // these two values are different approximations of PI + // the first one is approximately PI - 3.07e-18 + // the second one is approximately PI + 1.936e-17 + Fraction pi1 = new Fraction(1068966896, 340262731); + Fraction pi2 = new Fraction( 411557987, 131002976); + assertEquals(-1, pi1.compareTo(pi2)); + assertEquals( 1, pi2.compareTo(pi1)); + assertEquals(0.0, pi1.doubleValue() - pi2.doubleValue(), 1.0e-20); } public void testDoubleValue() {