我正在编写计算器演示。计算器接受用户输入(字符串)并进行一些计算。第一步是将字符串解析为双精度。
我正在使用NumberUtils.isParsable()
和Double.parseDouble()
。但是,我想限制用户输入,以便双精度数不会溢出。似乎parseDouble()
仅检查字符串是否为数字。我没有找到任何检查字符串值的方法。
我想知道这样做的最好方法是什么。
我认为“溢出”所指的数字太大而无法表示。
如果在“很大的数字”上调用Double.parseDouble()
,则实际上将获得INF值...也不例外1。因此,对溢出数字的简单解决方案2是使用Double.isInfinite(double)
测试调用Double.parseDouble(String)
的结果。
进行转换并测试(尝试)检查的结果,然后再进行测试,这将效率更高且代码更少。
1-我检查了Java 11源代码。查看jdk.internal.math.FloatingDecimal
的代码。评论有点有趣。
2-如果您毕业于“异常为恶”思想流派,则可以在调用parseDouble
之前使用正则表达式检查字符串的语法。我认为这是不必要的。只需处理异常。
您可以使用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
我想您可以做的是将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();
当然,以上代码假定句点(。)用于小数点(更改为您的要求)。