保护计算器不被 0 除

Protect calculator from dividing by 0

当用户试图在我的计算器中将某个数字除以 0 时,我希望在编译器中没有错误,但我不知道如何才能做到这一点。当用户执行计算器时,计算器的结果应该为 0,但我希望在 Java 编译器中没有错误。

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);
}

谁能帮我解决我的代码中的哪些问题?我是 Java 初学者,如果有任何建议或帮助,我将不胜感激。

这类似于:

但略有不同,因为此代码使用 BigDecimals 而不是双精度数,并且双精度数在除以零时的行为与 BigDecimal 不同。我最初将这个问题作为重复问题关闭,但由于差异而重新打开它。

对于 BigDecimal:

BigDecimal.valueOf(1).divide(BigDecimal.ZERO))

将抛出 ArithmeticException 而不是 return 结果,而将两个双精度相除不会抛出异常,而是 return 一个无限结果。

无论如何,正如 Ms3x 在评论中所建议的那样,无论如何进行除法,最好都以相同的方式进行编码。首先检查零值,只有在正确的值不为零时才执行除法。

注:

BigDecimal.valueOf(1).divide(BigDecimal.valueOf(3)

也会抛出 ArithmeticException,因为没有舍入的结果可能是无限长的数字,这不是您想要的。

此外,您正在尝试从 calculate() return display.setText("0"),但编译失败,因为计算需要 BigDecimal 结果和 display.setText("0 ) 将 return 无效(假设显示是一个 TextField,这似乎很可能)。

您应该对 calculate() 函数进行一些更改:

  1. calculate() 及其引用的任何字段都不应是静态的。
  2. 在除法之前检查 calculate() 中的正确值以确保它不为零。
    • return BigDecimal.ZERO 如果正确的值为零,如果这是你想要做的。
  3. 使用除法 rounding mode or math context
  4. 通过在这种情况下不尝试 return display.setText("0") 来修复 calculate() 中的编译错误
    • return BigDecimal.ZERO 如果这是你想要做的。

示例代码

遵循上面列出的建议修复。

它还使用了 switch expression,但如果您不想,则不需要使用它。

该示例使用断言,您使用 Java VM 参数启用它们 -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;
        };
    }
}

然后您可以轻松地将文本字段设置为结果:

display.setText(
    calculate(
        selectedOperator, left, right
    ).toString()
);