Java解析字符串以进行双重溢出检查

问题描述 投票:1回答:3

我正在编写计算器演示。计算器接受用户输入(字符串)并进行一些计算。第一步是将字符串解析为双精度。

我正在使用NumberUtils.isParsable()Double.parseDouble()。但是,我想限制用户输入,以便双精度数不会溢出。似乎parseDouble()仅检查字符串是否为数字。我没有找到任何检查字符串值的方法。

我想知道这样做的最好方法是什么。

java double
3个回答
0
投票

我认为“溢出”所指的数字太大而无法表示。

如果在“很大的数字”上调用Double.parseDouble(),则实际上将获得INF值...也不例外1。因此,对溢出数字的简单解决方案2是使用Double.isInfinite(double)测试调用Double.parseDouble(String)的结果。

进行转换并测试(尝试)检查的结果,然后再进行测试,这将效率更高且代码更少。


1-我检查了Java 11源代码。查看jdk.internal.math.FloatingDecimal的代码。评论有点有趣。

2-如果您毕业于“异常为恶”思想流派,则可以在调用parseDouble之前使用正则表达式检查字符串的语法。我认为这是不必要的。只需处理异常。


0
投票

您可以使用BigDecimal类根据double的最大值检查输入。

这是一种方法,如果提供的true表示一个小于或等于String的最大值的数值,则将返回double,而当输入的值大于最大值时将返回false double可以代表。

public static boolean isValidDouble(String input){
    final BigDecimal MAX_DOUBLE = new BigDecimal(Double.MAX_VALUE);
    try{
        BigDecimal bigInput = new BigDecimal(input);
        return bigInput.compareTo(MAX_DOUBLE) < 1;
    }catch(NumberFormatException e){
        return false;
    }
}

这里有一些代码可以测试上述方法:

    String[] inputs = {
            "1E999999999999999999999999999999999999999999999999999999999999999999999999999999",
            "1234",
            "1.7976931348623157E308",
            "1.79769313486231570E308",
            "1.79769313486231571E308",
            "1.79769313486231569E308",
            "1E400"
    };

    for(String input: inputs){
        System.out.println("input is: "+input);
        System.out.println("is valid double? " + String.valueOf(isValidDouble(input)));
    }

这里是上述测试的结果输出:

input is: 1E999999999999999999999999999999999999999999999999999999999999999999999999999999
is valid double? false
input is: 1234
is valid double? true
input is: 1.7976931348623157E308
is valid double? true
input is: 1.79769313486231570E308
is valid double? true
input is: 1.79769313486231571E308
is valid double? false
input is: 1.79769313486231569E308
is valid double? true
input is: 1E400
is valid double? false

-1
投票

我想您可以做的是将String#matches()方法与Regular Expression(RegEx)一起使用,以查看提供的字符串是浮点数还是有符号或无符号状态的整数值:

java.util.Scanner input = new java.util.Scanner(System.in);

Double doubleValue = null;
Integer intValue = null;
Long longValue = null;

String userInput = "";
while (userInput.equals("")) {
    System.out.print("Enter a numerical value: --> ");
    userInput = input.nextLine();
    if (!userInput.matches("[-+]?\\d+\\.?\\d+([eE][-+]?\\d+)?")) {
        System.err.println("Invalid numerical value supplied!");
        userInput = "";
    }
}
/* Now we know that the supplied string numerical value is
   either a signed or unsigned floating point or Integer
   value.      */
// Is it a double value...
if (userInput.contains(".")) {
    // Yes it is...
    // Is it within Double Min/Max values
    try {
        doubleValue = Double.parseDouble(userInput);
    }
    catch (Exception ex) {
        System.err.println("The User's numerical value supplied (" + userInput
                + ") exceeds limits for a Double data type!");
        System.err.println("Perhaps consider using BigDecimal!");
    }
}
else {
    // It must a an Integer Type of either Long or int...
    try {
        long tmp = Long.parseLong(userInput);
        if (tmp >= Integer.MIN_VALUE && tmp <= Integer.MAX_VALUE) {
            intValue = (int) tmp;
        }
        else {
            longValue = tmp;
        }
    }
    catch (Exception ex) {
        System.err.println("The User's numerical value supplied (" + userInput
                + ") exceeds limits for a Long data type!");
        System.err.println("Perhaps consider using BigInteger!");
    }
}

System.out.println();
System.out.println("Integer (int) Value:   " + intValue);
System.out.println("Integer (long) Value:  " + longValue);
System.out.println("Double Value:          " + doubleValue);
System.out.println();

当然,以上代码假定句点()用于小数点(更改为您的要求)。

© www.soinside.com 2019 - 2024. All rights reserved.