来自字符串的数值

Numeric values from a String

我正在创建一个物理计算器,目前正在研究平均速度。对于位移,我希望用户输入一个字符串,即“5km north”。然后使用一种方法仅使用 Double.parseDouble 或类似方法将字符串中的数值分配为双精度值。

下面是我提取数值的方法

        private double getNumericalValue(String userInput) {
        double numericalOutput = 0.0;
        for (int i = 0; i < userInput.length(); i++) {
            if (userInput.charAt(i) >= 65 && userInput.charAt(i) <= 122) {
                numericalOutput = Double.parseDouble(userInput.substring(0, i));
            }
        }
        return numericalOutput;
    }

最后是 getAverageVelocity 方法

        private void getAverageVelocity() {
        // formula average velocity = displacement s / change in time t
        double avgVelocity = 0.0;
        System.out.println("Enter the displacement: [ex. 5 km north]");
        String displacement = getStringInput();
        System.out.println("Enter the change in time: [ex. 1 hour]");
        String changeInTime = getStringInput();
        // parse the string and change numerical input into double
        double numericalS = getNumericalValue(displacement);
        double numericalT = getNumericalValue(changeInTime);

        avgVelocity = numericalS / numericalT;

        System.out.println("The Average Velocity is: " + avgVelocity);
    }

如您所见,我想我可以简单地将字符与其 ascii 值进行比较。但是,它在我的双输出中包含 k 或 space,这会引发此错误。

Exception in thread "main" java.lang.NumberFormatException: For input string: "5 k"
at java.base/jdk.internal.math.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2054)
at java.base/jdk.internal.math.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
at java.base/java.lang.Double.parseDouble(Double.java:556)
at Main.getNumericalValue(Main.java:122)
at Main.getAverageVelocity(Main.java:393)
at Main.kineticsIn1DCalculator(Main.java:375)
at Main.performAction(Main.java:141)
at Main.runner(Main.java:29)
at Main.main(Main.java:22)

任何帮助和详尽的解释都会很棒。谢谢

你有错误,因为即使找到第一个数字,for 循环仍在继续。您只需添加 break 指令,然后 for 循环在找到的第一个数字处结束。

这是方法的最终代码getNumericalValue:

private double getNumericalValue(String userInput) {
    double numericalOutput = 0.0;
    for (int i = 0; i < userInput.length(); i++) {
        if (userInput.charAt(i) >= 65 && userInput.charAt(i) <= 122) {
            numericalOutput = Double.parseDouble(userInput.substring(0, i));
            break;
        }
    }
    return numericalOutput;
}

您只需输入该行并解析其部分。

最好引入一个class来保存一个带单位的值,其中“km north”算作一个单位。

因为 java 14 存在 record class.

record ValueWithUnit(double value, String unit) {
    public static ValueWithUnit from(String s) {
        String v = s.replaceFirst("^(.*?)([ A-z].*)$", "");
        String u = s.replaceFirst("^(.*?)([ A-z].*)$", "");
        if (u == v) {
            u = "";
        }
        double x = Double.parseDouble(v); // Replaces getNumericalValue(v);
        return new Value(x, u);
    }

    @Override
    public String toString() {
        String.format("%f %s", value, unit);
    }
}

您可以直接将其用作:

ValueWithUnit vu = new ValueWithUnit(30.0, "km");
System.out.println(vu);

代码则变为:

private void getAverageVelocity() {
    // formula average velocity = displacement s / change in time t
    double avgVelocity = 0.0;
    System.out.println("Enter the displacement: [ex. 5 km north]");
    ValueWithUnit displacement = ValueWithUnit.from(getStringInput());
    System.out.println("Enter the change in time: [ex. 1 hour]");
    ValueWithUnit changeInTime = ValueWithUnit.from(getStringInput());
    // parse the string and change numerical input into double
    double numericalS = displacement.value;
    double numericalT = changeInTime.value;

    avgVelocity = numericalS / numericalT;

    System.out.printf("The Average Velocity is: %f %s%n", avgVelocity,
        displacement.unit + "/" + changeInTime.unit);
}

你在 if 块中实际测试的是 i 处的字符是否是字母 A-Z、a-z 和其他符号(即 [ ^ ], ...etc) 检查它是否是一个数字(即 0-9)对应的十进制范围是 48-57 check this link

至于异常是因为 substring(0, 0) 会产生一个空字符串,当试图解析它时,Double.parseDouble() 会抛出异常。 这是您可以使用的解决方案:

    private double getNumericalValue(String userInput) {
    double numericalOutput = 0.0;
    for (int i = 0; i < userInput.length(); i++) {
        if (userInput.charAt(i) >= 48 && userInput.charAt(i) <= 57) {
            numericalOutput = Double.parseDouble(userInput.substring(0, i + 1));
        }
    }
    return numericalOutput;
}

注:substring(i, j) i 含,j 不含

更新: 刚刚注意到,在你的情况下发生异常是因为你试图解析字母“k”因为它通过了条件,导致 Double.parseDouble() 抛出异常。