-
Bug
-
Resolution: Not an Issue
-
P4
-
None
-
17
-
generic
-
generic
ADDITIONAL SYSTEM INFORMATION :
Windows 10
A DESCRIPTION OF THE PROBLEM :
BigDecimal rounding does not work as expected during multiplication/division, when provided with MathContext having the precision details.
After multiplication/division, if we set the scale like below, it works as expected
.setScale(8, BigDecimal.ROUND_HALF_UP)
But if we provide the equivalent scale using MathContext, like below, it does not round it properly, but instead truncates it by 2 decimal places..!
new MathContext(8, RoundingMode.HALF_UP)
Also, during division, if we directly divide a BigDecimal with another without specifying precision details, we get an exception. (This works with multiplication though)
BigDecimal quantity = new BigDecimal(178643);
val1 = quantity.divide(new BigDecimal(1.0394)); // Exception at this point - "java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result."
"java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result."
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
// Multiplication -- using setScale
BigDecimal quantity = new BigDecimal(178643);
BigDecimal val1 = quantity.multiply(new BigDecimal(1.0394)).setScale(8, BigDecimal.ROUND_HALF_UP);
// Multiplication -- precision by using MathContext.
BigDecimal val2 = quantity.multiply(new BigDecimal(1.0394), new MathContext(8, RoundingMode.HALF_UP));
System.out.println("After multiplication, with normal rounding, val1 =" + val1
+ ", rounding using math context, val2=" + val2);
// Division -- using setScale -- This produces an error:
// "java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result."
// val1 = quantity.divide(new BigDecimal(1.0394)).setScale(8, BigDecimal.ROUND_HALF_UP);
// Division -- passing the scale and rounding mode - works fine.
val1 = quantity.divide(new BigDecimal(1.0394), 8, RoundingMode.HALF_UP);
// Division -- precision by using MathContext.
val2 = quantity.divide(new BigDecimal(1.0394), new MathContext(8, RoundingMode.HALF_UP));
System.out.println("After division, with normal rounding, val1 =" + val1 + ", rounding using math context, val2=" + val2);
Try the above code in a simple java program
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
185681.53420000 (in case of multiplication)
171871.27188763 (in case of division)
ACTUAL -
185681.53 (in case of multiplication)
171871.27 (in case of division)
---------- BEGIN SOURCE ----------
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
public class MathContextIssues {
public static void main(String[] args) {
// TODO Auto-generated method stub
// Multiplication -- using setScale
BigDecimal quantity = new BigDecimal(178643);
BigDecimal val1 = quantity.multiply(new BigDecimal(1.0394)).setScale(8, BigDecimal.ROUND_HALF_UP);
// Multiplication -- precision by using MathContext.
BigDecimal val2 = quantity.multiply(new BigDecimal(1.0394), new MathContext(8, RoundingMode.HALF_UP));
System.out.println("After multiplication, with normal rounding, val1 =" + val1
+ ", rounding using math context, val2=" + val2);
// Division -- using setScale -- This produces an error:
// "java.lang.ArithmeticException: Non-terminating decimal expansion; no exact
// representable decimal result."
// val1 = quantity.divide(new BigDecimal(1.0394)).setScale(8,
// BigDecimal.ROUND_HALF_UP);
// Division -- passing the scale and rounding mode - works fine.
val1 = quantity.divide(new BigDecimal(1.0394), 8, RoundingMode.HALF_UP);
// Division -- precision by using MathContext.
val2 = quantity.divide(new BigDecimal(1.0394), new MathContext(8, RoundingMode.HALF_UP));
System.out.println(
"After division, with normal rounding, val1 =" + val1 + ", rounding using math context, val2=" + val2);
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
.setScale(8, BigDecimal.ROUND_HALF_UP) // for multiplication
.divide(new BigDecimal(1.0394), 8, RoundingMode.HALF_UP); // for division
FREQUENCY : always
Windows 10
A DESCRIPTION OF THE PROBLEM :
BigDecimal rounding does not work as expected during multiplication/division, when provided with MathContext having the precision details.
After multiplication/division, if we set the scale like below, it works as expected
.setScale(8, BigDecimal.ROUND_HALF_UP)
But if we provide the equivalent scale using MathContext, like below, it does not round it properly, but instead truncates it by 2 decimal places..!
new MathContext(8, RoundingMode.HALF_UP)
Also, during division, if we directly divide a BigDecimal with another without specifying precision details, we get an exception. (This works with multiplication though)
BigDecimal quantity = new BigDecimal(178643);
val1 = quantity.divide(new BigDecimal(1.0394)); // Exception at this point - "java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result."
"java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result."
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
// Multiplication -- using setScale
BigDecimal quantity = new BigDecimal(178643);
BigDecimal val1 = quantity.multiply(new BigDecimal(1.0394)).setScale(8, BigDecimal.ROUND_HALF_UP);
// Multiplication -- precision by using MathContext.
BigDecimal val2 = quantity.multiply(new BigDecimal(1.0394), new MathContext(8, RoundingMode.HALF_UP));
System.out.println("After multiplication, with normal rounding, val1 =" + val1
+ ", rounding using math context, val2=" + val2);
// Division -- using setScale -- This produces an error:
// "java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result."
// val1 = quantity.divide(new BigDecimal(1.0394)).setScale(8, BigDecimal.ROUND_HALF_UP);
// Division -- passing the scale and rounding mode - works fine.
val1 = quantity.divide(new BigDecimal(1.0394), 8, RoundingMode.HALF_UP);
// Division -- precision by using MathContext.
val2 = quantity.divide(new BigDecimal(1.0394), new MathContext(8, RoundingMode.HALF_UP));
System.out.println("After division, with normal rounding, val1 =" + val1 + ", rounding using math context, val2=" + val2);
Try the above code in a simple java program
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
185681.53420000 (in case of multiplication)
171871.27188763 (in case of division)
ACTUAL -
185681.53 (in case of multiplication)
171871.27 (in case of division)
---------- BEGIN SOURCE ----------
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
public class MathContextIssues {
public static void main(String[] args) {
// TODO Auto-generated method stub
// Multiplication -- using setScale
BigDecimal quantity = new BigDecimal(178643);
BigDecimal val1 = quantity.multiply(new BigDecimal(1.0394)).setScale(8, BigDecimal.ROUND_HALF_UP);
// Multiplication -- precision by using MathContext.
BigDecimal val2 = quantity.multiply(new BigDecimal(1.0394), new MathContext(8, RoundingMode.HALF_UP));
System.out.println("After multiplication, with normal rounding, val1 =" + val1
+ ", rounding using math context, val2=" + val2);
// Division -- using setScale -- This produces an error:
// "java.lang.ArithmeticException: Non-terminating decimal expansion; no exact
// representable decimal result."
// val1 = quantity.divide(new BigDecimal(1.0394)).setScale(8,
// BigDecimal.ROUND_HALF_UP);
// Division -- passing the scale and rounding mode - works fine.
val1 = quantity.divide(new BigDecimal(1.0394), 8, RoundingMode.HALF_UP);
// Division -- precision by using MathContext.
val2 = quantity.divide(new BigDecimal(1.0394), new MathContext(8, RoundingMode.HALF_UP));
System.out.println(
"After division, with normal rounding, val1 =" + val1 + ", rounding using math context, val2=" + val2);
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
.setScale(8, BigDecimal.ROUND_HALF_UP) // for multiplication
.divide(new BigDecimal(1.0394), 8, RoundingMode.HALF_UP); // for division
FREQUENCY : always