Issue
I want to get no errors in compiler when user tries to divide some number by 0 in my Calculator but I don't know exactly how can I achieve this. The result in calculator should be 0 when user does it but I want to get no error in Java compiler.
protected void handleOnAnyButtonClicked(ActionEvent evt) {
Button button = (Button)evt.getSource();
final String buttonText = button.getText();
if (buttonText.equals("C") || buttonText.equals("AC")) {
if (buttonText.equals("AC")) {
left = BigDecimal.ZERO;
}
selectedOperator = "";
numberInputting = false;
display.setText("0");;
return;
}
if (buttonText.matches("[0-9\\.]")) {
if (!numberInputting) {
numberInputting = true;
display.clear();
}
display.appendText(buttonText);
return;
}
if (buttonText.matches("[+-×÷]")) {
left = new BigDecimal(display.getText());
selectedOperator = buttonText;
numberInputting = false;
return;
}
if (buttonText.equals("=")) {
final BigDecimal right = numberInputting ? new BigDecimal(display.getText()) : left;
left = calculate(selectedOperator, left, right);
display.setText(left.toString());
numberInputting = false;
return;
}
}
static BigDecimal calculate(String operator, BigDecimal left, BigDecimal right) {
switch (operator) {
case "+":
return left.add(right);
case "-":
return left.subtract(right);
case "×":
return left.multiply(right);
case "÷":
// if user divides by 0
try {
left.divide(right);
} catch(ArithmeticException e) {
e.printStackTrace();
return display.setText("0");
}
return left.divide(right);
default:
}
return right;
}
public static void main(String[] args) {
launch(args);
}
Could anyone help me what should I fix in my code? I'm a Java beginner and I would be very thankful for any advice or help.
Solution
This is similar to:
but slightly different because this code uses BigDecimals rather than doubles, and doubles behave differently from BigDecimal under divide by zero. I originally closed this question as a duplicate but reopened it, due to the differences.
For a BigDecimal:
BigDecimal.valueOf(1).divide(BigDecimal.ZERO))
will throw an ArithmeticException rather than return a result, whereas dividing two doubles will not throw an exception but will instead return an infinite result.
Regardless, as suggested by Ms3x in comments, it is probably best to code the same way no matter how the division occurs. Check for the zero value first and only perform the divide if the right value is not zero.
Note:
BigDecimal.valueOf(1).divide(BigDecimal.valueOf(3)
will also throw an ArithmeticException because the result without rounding could be an infinitely long number, which is not what you want.
Additionally, you are trying to return display.setText("0") from calculate(), which fails to compile because calculate requires a BigDecimal result and display.setText("0) will return void (assuming display is a TextField, which seems likely).
You should make a few changes to your calculate() function:
- calculate() and any fields it references should not be static.
- Check the right value in calculate() to make sure it is not zero before dividing.
- return BigDecimal.ZERO if the right value is zero, if that is what you want to do.
- Use divide with a rounding mode or math context.
- Fix the compilation error in calculate() by not trying to return display.setText("0"), in such a case
- return BigDecimal.ZERO if that is what you want to do.
Example Code
Follows the recommended fixes outlined above.
It also uses a switch expression, though you don't need to use that if you don't want to.
The example uses asserts, you enable them with the Java VM argument -ea
.
import java.math.BigDecimal;
import java.math.MathContext;
public class BigDecimalTest {
public static void main(String[] args) {
BigDecimal result;
BigDecimalTest test = new BigDecimalTest();
result = test.calculate("÷", BigDecimal.valueOf(1), BigDecimal.valueOf(3));
assert(BigDecimal.valueOf(0.3333333).equals(result));
result = test.calculate("÷", BigDecimal.valueOf(28.2), BigDecimal.valueOf(0));
assert(BigDecimal.ZERO.equals(result));
}
private BigDecimal calculate(String operator, BigDecimal left, BigDecimal right) {
return switch (operator) {
case "+" -> left.add(right);
case "-" -> left.subtract(right);
case "×" -> left.multiply(right);
case "÷" ->
BigDecimal.ZERO.equals(right)
? BigDecimal.ZERO
: left.divide(right, MathContext.DECIMAL32);
default -> right;
};
}
}
Then you can easily set your text field to the result:
display.setText(
calculate(
selectedOperator, left, right
).toString()
);
Answered By - jewelsea
Answer Checked By - Willingham (JavaFixing Volunteer)