NUMBERS-15: Fix overflow in "BigFraction".
Thanks to Sergey Ushakov.
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 @@
*/
@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 @@
*/
@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(),
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 @@
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);
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 @@
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>