NUMBERS-15: Fix overflow in "BigFraction". Thanks to Sergey Ushakov.
Project: http://git-wip-us.apache.org/repos/asf/commons-numbers/repo Commit: http://git-wip-us.apache.org/repos/asf/commons-numbers/commit/b37c9f19 Tree: http://git-wip-us.apache.org/repos/asf/commons-numbers/tree/b37c9f19 Diff: http://git-wip-us.apache.org/repos/asf/commons-numbers/diff/b37c9f19 Branch: refs/heads/complex-dev Commit: b37c9f195f28f897eadadaf1f2df86bca0b8ce7c Parents: c15e3b9 Author: Gilles Sadowski <gil...@harfang.homelinux.org> Authored: Sun Mar 19 18:43:49 2017 +0100 Committer: Gilles Sadowski <gil...@harfang.homelinux.org> Committed: Sun Mar 19 18:43:49 2017 +0100 ---------------------------------------------------------------------- .../commons/numbers/fraction/BigFraction.java | 16 ++++++++++---- .../numbers/fraction/BigFractionTest.java | 22 ++++++++++++++++++++ src/changes/changes.xml | 5 +++-- 3 files changed, 37 insertions(+), 6 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/commons-numbers/blob/b37c9f19/commons-numbers-fraction/src/main/java/org/apache/commons/numbers/fraction/BigFraction.java ---------------------------------------------------------------------- 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 eab9b7f..a76eb45 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 @@ -695,8 +695,12 @@ public class BigFraction */ @Override public double doubleValue() { - double result = numerator.doubleValue() / denominator.doubleValue(); - if (Double.isNaN(result)) { + double doubleNum = numerator.doubleValue(); + double doubleDen = denominator.doubleValue(); + double result = doubleNum / doubleDen; + if (Double.isInfinite(doubleNum) || + Double.isInfinite(doubleDen) || + Double.isNaN(result)) { // Numerator and/or denominator must be out of range: // Calculate how far to shift them to put them in range. int shift = Math.max(numerator.bitLength(), @@ -748,8 +752,12 @@ public class BigFraction */ @Override public float floatValue() { - float result = numerator.floatValue() / denominator.floatValue(); - if (Double.isNaN(result)) { + float floatNum = numerator.floatValue(); + float floatDen = denominator.floatValue(); + float result = floatNum / floatDen; + if (Float.isInfinite(floatNum) || + Float.isInfinite(floatDen) || + Float.isNaN(result)) { // Numerator and/or denominator must be out of range: // Calculate how far to shift them to put them in range. int shift = Math.max(numerator.bitLength(), http://git-wip-us.apache.org/repos/asf/commons-numbers/blob/b37c9f19/commons-numbers-fraction/src/test/java/org/apache/commons/numbers/fraction/BigFractionTest.java ---------------------------------------------------------------------- diff --git a/commons-numbers-fraction/src/test/java/org/apache/commons/numbers/fraction/BigFractionTest.java b/commons-numbers-fraction/src/test/java/org/apache/commons/numbers/fraction/BigFractionTest.java index 55982ea..e17eb2a 100644 --- a/commons-numbers-fraction/src/test/java/org/apache/commons/numbers/fraction/BigFractionTest.java +++ b/commons-numbers-fraction/src/test/java/org/apache/commons/numbers/fraction/BigFractionTest.java @@ -233,6 +233,28 @@ public class BigFractionTest { Assert.assertEquals(5, large.floatValue(), 1e-15); } + // NUMBERS-15 + @Test + public void testDoubleValueForLargeNumeratorAndSmallDenominator() { + final BigInteger pow300 = BigInteger.TEN.pow(300); + final BigInteger pow330 = BigInteger.TEN.pow(330); + final BigFraction large = new BigFraction(pow330.add(BigInteger.ONE), + pow300); + + Assert.assertEquals(1e30, large.doubleValue(), 1e-15); + } + + // NUMBERS-15 + @Test + public void testFloatValueForLargeNumeratorAndSmallDenominator() { + final BigInteger pow30 = BigInteger.TEN.pow(30); + final BigInteger pow40 = BigInteger.TEN.pow(40); + final BigFraction large = new BigFraction(pow40.add(BigInteger.ONE), + pow30); + + Assert.assertEquals(1e10f, large.floatValue(), 1e-15); + } + @Test public void testFloatValue() { BigFraction first = new BigFraction(1, 2); http://git-wip-us.apache.org/repos/asf/commons-numbers/blob/b37c9f19/src/changes/changes.xml ---------------------------------------------------------------------- diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 941d628..06fdc65 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -56,8 +56,9 @@ This is the first release of Apache Commons Numbers. Apache Commons Numbers 1.0 contains the following modules: TBD "> - <!-- <action dev="erans" type="fix" issue="NUMBERS-xxx"> --> - <!-- </action> --> + <action dev="sushakov" type="fix" issue="NUMBERS-15"> + "BigFraction": Fixed overflow "doubleValue()" and "floatValue()". + </action> </release> </body>