diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml index 5700f1deb..087d6eb22 100644 --- a/src/documentation/content/xdocs/status.xml +++ b/src/documentation/content/xdocs/status.xml @@ -34,6 +34,7 @@ + 51339 - Fixed arithmetic rounding in formula evaluation 51356 - Support autoSizeColumn in SXSSF 51335 - Parse picture goal and crop sizes in HWPF 51305 - Add sprmTCellPaddingDefault support in HWPF diff --git a/src/java/org/apache/poi/ss/formula/functions/MathX.java b/src/java/org/apache/poi/ss/formula/functions/MathX.java index 4914ad506..5696c51f8 100644 --- a/src/java/org/apache/poi/ss/formula/functions/MathX.java +++ b/src/java/org/apache/poi/ss/formula/functions/MathX.java @@ -53,13 +53,7 @@ final class MathX { retval = Double.NaN; } else { - if (p != 0) { - double temp = Math.pow(10, p); - retval = Math.round(n*temp)/temp; - } - else { - retval = Math.round(n); - } + retval = java.math.BigDecimal.valueOf(n).setScale(p, java.math.RoundingMode.HALF_UP).doubleValue(); } return retval; @@ -87,22 +81,7 @@ final class MathX { retval = Double.NaN; } else { - if (p != 0) { - double temp = Math.pow(10, p); - double nat = Math.abs(n*temp); - - retval = sign(n) * - ((nat == (long) nat) - ? nat / temp - : Math.round(nat + 0.5) / temp); - } - else { - double na = Math.abs(n); - retval = sign(n) * - ((na == (long) na) - ? na - : (long) na + 1); - } + retval = java.math.BigDecimal.valueOf(n).setScale(p, java.math.RoundingMode.UP).doubleValue(); } return retval; @@ -130,13 +109,7 @@ final class MathX { retval = Double.NaN; } else { - if (p != 0) { - double temp = Math.pow(10, p); - retval = sign(n) * Math.round((Math.abs(n)*temp) - 0.5)/temp; - } - else { - retval = (long) n; - } + retval = java.math.BigDecimal.valueOf(n).setScale(p, java.math.RoundingMode.DOWN).doubleValue(); } return retval; diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestMathX.java b/src/testcases/org/apache/poi/ss/formula/functions/TestMathX.java index dd6974b35..1f5c4c8e8 100644 --- a/src/testcases/org/apache/poi/ss/formula/functions/TestMathX.java +++ b/src/testcases/org/apache/poi/ss/formula/functions/TestMathX.java @@ -672,6 +672,9 @@ public class TestMathX extends AbstractNumericTestCase { d = 150.0; p = -2; assertEquals("round ", 200, MathX.round(d, p)); + + d = 2162.615d; p = 2; + assertEquals("round ", 2162.62d, MathX.round(d, p)); } public void testRoundDown() { diff --git a/src/testcases/org/apache/poi/ss/usermodel/BaseTestFormulaEvaluator.java b/src/testcases/org/apache/poi/ss/usermodel/BaseTestFormulaEvaluator.java index f8d71f94c..1542c3609 100644 --- a/src/testcases/org/apache/poi/ss/usermodel/BaseTestFormulaEvaluator.java +++ b/src/testcases/org/apache/poi/ss/usermodel/BaseTestFormulaEvaluator.java @@ -281,4 +281,23 @@ public abstract class BaseTestFormulaEvaluator extends TestCase { assertEquals(3.5, cellB1.getNumericCellValue(), 0.0); } + + public void testRounding_bug51339() { + Workbook wb = _testDataProvider.createWorkbook(); + Sheet sheet = wb.createSheet("Sheet1"); + Row row = sheet.createRow(0); + Cell cellA1 = row.createCell(0); + cellA1.setCellValue(2162.615d); + Cell cellB1 = row.createCell(1); + cellB1.setCellFormula("round(a1,2)"); + Cell cellC1 = row.createCell(2); + cellC1.setCellFormula("roundup(a1,2)"); + Cell cellD1 = row.createCell(3); + cellD1.setCellFormula("rounddown(a1,2)"); + FormulaEvaluator fe = wb.getCreationHelper().createFormulaEvaluator(); + + assertEquals(2162.62, fe.evaluateInCell(cellB1).getNumericCellValue(), 0.0); + assertEquals(2162.62, fe.evaluateInCell(cellC1).getNumericCellValue(), 0.0); + assertEquals(2162.61, fe.evaluateInCell(cellD1).getNumericCellValue(), 0.0); + } } \ No newline at end of file