While performing mathematical operations to develop an android application for a simple calculator, resulted in strange results for subtraction and division operation. Other operations goes well with the inputs provided. In my research for precision handling, came across BigDecimal class that lessen down my errors.
Certain operations like subtraction and division have not yielded proper results. I am providing with the code snippet here.
.
.
.
String answer = "";
BigDecimal bigDecimal1, bigDecimal2;
BigDecimal bigDecimalResult;
String operation = "";
.
.
.
case R.id.button_substraction:
bigDecimal1 = new BigDecimal(answer);
operation = "-";
answer = "";
textViewAnswer.setText(buttonSubstraction.getText().toString());
break;
case R.id.button_division:
bigDecimal1 = new BigDecimal(answer);
operation = "/";
answer = "";
textViewAnswer.setText(buttonDivision.getText().toString());
break;
case R.id.button_equal:
bigDecimal2 = new BigDecimal(answer);
answer = "";
switch (operation) {
.
.
case "-":
bigDecimalResult = (bigDecimal1.subtract(bigDecimal2)).setScale(6,RoundingMode.HALF_UP).stripTrailingZeros();
textViewAnswer.setText(bigDecimalResult.toString());
break;
case "/":
bigDecimalResult = (bigDecimal1.divide(bigDecimal2)).setScale(6,RoundingMode.HALF_UP).stripTrailingZeros();
textViewAnswer.setText(bigDecimalResult.toString());
break;
}
.
.
.
Example:
when a number is subtracted from itself, it results 0 with the precision value 6(set in the code) as,
100 - 100 = 0.000000
Even though stripTrailingZeros() is specified.
Attempting to divide
1 / 9
crashes my app.
Your problem with stripTrailingZeros()
not stripping a zero value was fixed in Java 8.
See JDK-6480539: BigDecimal.stripTrailingZeros() has no effect on zero itself ("0.0")
Your problem with 1 / 9
crashing your app, is caused by your logic:
bigDecimalResult = bigDecimal1.divide(bigDecimal2)
.setScale(6, RoundingMode.HALF_UP)
.stripTrailingZeros()
You are trying to set the scale after dividing, but there is no exact value for 1 / 9
, so the divide()
method throws an exception, as documented in the javadoc.
Throws
ArithmeticException
if the exact quotient does not have a terminating decimal expansion
You should call one of the other overloads of the divide()
method:
bigDecimalResult = bigDecimal1.divide(bigDecimal2, 6, RoundingMode.HALF_UP)
.stripTrailingZeros()
Now, beware result of stripTrailingZeros()
. E.g. if result is 100.00000
, stripTrailingZeros()
will literally strip all the zeros, resulting in 1E+2
. That is probably not what you want.
To get that printed in a more human readable way, you might want to use toPlainString()
instead of toString()
.