表示数值的字符串 -- java
题目描述
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。
例如,字符串 “+100”,“5e2”,"-123",“3.1416” 和 “-1E-16” 都表示数值。但是 “12e”,“1a3.14”,“1.2.3”,“±5” 和 “12e+4.3” 都不是。
解题思路
非正则表达式解法
表示数值的字符串遵循模式A[.[B]][e|EC]
或者.B[e|EC]
。
其中A为数值的整数部分,B紧跟着小数点为数值的小数部分,C紧跟着’e’或者‘E’为数值的指数部分。在小数里可能没有数值的整数部分。例如,小数.123等于0.123。因此A部分不是必需的,如果一个数没有整数部分,那么它的小数部分不能为空。
上诉A和C都是可能以‘+’或者‘-’开头的0-9的数字串;B也是0-9的数位串,但前面不能有正负号。
判断一个字符串是否符合上述模式时,首先尽可能多地扫描0-9的数位(有可能在起始处有‘+’或者‘-’),也就是前面模式中表示数值的A部分,如果遇到小数点’.’,则开始扫描数值小数部分的B部分。如果遇到’e’或者‘E’,则开始扫描数值指数的C部分。
正则表达式解法
使用正则表达式进行匹配:
[] : 字符集合
() : 分组,在这里是为了让表达式更清晰
? : 重复 0 ~ 1 次
+ : 重复 1 ~ n 次
* : 重复 0 ~ n 次
. : 任意字符
\\. : 转义后的.
\\d : 任意数字
代码
非正则表达式解法
public class IsNumberic {
// 定义str的索引位置
private static int i = 0;
public static boolean isNumberic(char[] str) {
// 防止非法输入
if (str == null) {
return false;
}
// 1. 扫描A
boolean numberic = scanInteger(str);
// 2. 扫描B
if (i < str.length && str[i] == '.') {
i++;
// 下面一行代码用||的原因
// 1. 小数可以没有整数部分,如.123等于0.123
// 2. 小数点后面可以没有数字,如233.等于233.0
// 3. 当然,小数点前面和后面可以都有数字,如233.666
numberic = numberic || scanUnsignedInteger(str);
}
// 3. 扫描C
if (i < str.length && (str[i] == 'e' || str[i] == 'E')) {
i++;
// 下面一行代码用&&的原因:
// 1.当e或者E前面没有数字时,整个字符串不能表示数字,如.e1、e1;
// 2.当e或者E后面没有整数时,整个字符串不能表示数字,如12e、12e+5.4;
numberic = numberic && scanInteger(str);
}
return numberic && i == str.length;
}
// 扫描是否有 无符号整数部分(在起始处不可能有‘+’或者‘-’)
public static boolean scanUnsignedInteger(char[] str) {
int before = i;
while (i < str.length && str[i] >= '0' && str[i] <= '9') {
i++;
}
return i > before;
}
// 扫描是否有 整数部分(有可能在起始处有‘+’或者‘-’)
public static boolean scanInteger(char[] str) {
if (i < str.length && (str[i] == '+' || str[i] == '-')) {
i++;
}
return scanUnsignedInteger(str);
}
// 测试
public static void main(String[] args) {
String str = "+100";
System.out.println(isNumberic(str.toCharArray())); // true
// 将索引i恢复为0
i = 0;
str = "5e2";
System.out.println(isNumberic(str.toCharArray())); // true
// 将索引i恢复为0
i = 0;
str = "12e";
System.out.println(isNumberic(str.toCharArray())); // false
}
}
正则表达式解法
// 正则表达式解法
public class isNumberic_2 {
public static boolean isNumberic_2(String str) {
// 防止特殊输入
if (str == null || str.length() < 0) {
return false;
}
return new String(str).matches("[+-]?[\\d]*[\\.]?[\\d]*([eE][+-]?\\d+)?");
}
public static void main(String[] args) {
System.out.println(isNumberic_2("233."));
}
}
来自:
《剑指Offer》
Coding-Interviews/表示数值的字符串.md at master · todorex/Coding-Interviews