【问题标题】:Protect calculator from dividing by 0防止计算器除以 0
【发布时间】:2022-01-09 18:32:09
【问题描述】:

当用户尝试在我的计算器中将某个数字除以 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 初学者,如果能提供任何建议或帮助,我将不胜感激。

【问题讨论】:

  • 除以 0 时不会出现异常,所以在尝试除以之前检查 right 是否为 0。如果是display.setText("0")

标签: java javafx bigdecimal


【解决方案1】:

这类似于:

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

对于 BigDecimal:

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

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

无论如何,正如 cmets 中的 Ms3x 所建议的那样,无论除法如何发生,最好以相同的方式编写代码。首先检查零值,如果正确的值不为零,则只执行除法。

注意:

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

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

此外,您试图从 calculate() 返回 display.setText("0"),但由于计算需要 BigDecimal 结果而无法编译,因此 display.setText("0) 将返回 void(假设 display 是 TextField ,这似乎很可能)。

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

  1. calculate() 及其引用的任何字段都不应是静态的。
  2. 检查calculate() 中的正确值,确保除法前它不为零。
    • 如果正确的值为零,则返回 BigDecimal.ZERO,如果这是您想要的。
  3. 将除法与rounding mode or math context 结合使用。
  4. 通过在这种情况下不尝试返回 display.setText("0") 来修复 calculate() 中的编译错误
    • 如果您想要这样做,则返回 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()
);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-11
    • 1970-01-01
    • 1970-01-01
    • 2018-02-02
    • 1970-01-01
    • 2018-04-29
    相关资源
    最近更新 更多