题目
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100"、“5e2”、"-123"、“3.1416”、“0123"都表示数值,但"12e”、“1a3.14”、“1.2.3”、“±5”、"-1E-16"及"12e+5.4"都不是。
解题思路
数值的字符串遵循模式:A[.[B]][eC] 或者 .B[eC],其中 A 表示数值的整数部分,B 紧跟着小数点为数值的小数部分,C紧跟着 ‘e’ 为数值的指数部分。A 和 C 可能都是以 ‘+’ 或者 ‘-’ 开头的数字串,而 B 前面不能有正负号。
在小数里,可能没有数值的整数部分,例如小数 .123 等于 0.123,因此整数部分 A 不是必须的。如果一个数没有整数部分,那么它的小数部分不能为空。
判断一个字符串是否符合上述模式时,首先尽可能地扫描 0~9 的数位(可能包含正负号),也就是 A 部分。如果遇到小数点,则开始扫描 B 部分。如果遇到 ‘e’,则开始扫描 C 部分。
代码
class Solution {
public boolean isNumber(String s) {
// 先去除字符串首尾两端空格
String str = s.trim();
if(str.length()==0){
return false;
}
boolean flag = false;
int n = str.length();
// 一、先扫描整数部分
int i = 0;
int a = 0;
if(str.charAt(i) == '+' || str.charAt(i) == '-'){
i++;
}
a = i;
while(a<n && str.charAt(a)>='0' && str.charAt(a)<='9'){
a++;
}
// 判断整数部分是否存在
flag = a>i;
int j = a;
int b = a;
// 二、如果出现'.',则接下来是小数部分
if(j<n && str.charAt(j) == '.'){
j++;
b = j;
while(b<n && str.charAt(b)>='0' && str.charAt(b)<='9'){
b++;
}
// 1、小数可以没有整数部分,这种情况小数点后面必须有数字,例如 .123 等于 0.123
// 2、小数点后面可以没有数字,这种情况就必须有整数部分,例如 233. 等于 233.0
// 3、小数点前后都有数字,例如 233.123
flag = flag || (b>j);
}
int k = b;
int c = b;
// 三、如果出现'e',则接下来是指数部分
if(k<n && str.charAt(k)=='e'){
k++;
if(k<n && (str.charAt(k) == '+' || str.charAt(k) == '-')){
k++;
}
c = k;
while(c<n && str.charAt(c)>='0' && str.charAt(c)<='9'){
c++;
}
// 1、'e' 前面没有数字时,整个字符串不能表示数字,例如 .e1
// 2、'e' 后面没有整数时,整个字符串不能表示数字,例如 12e、12e+5.4
flag = flag && (c>k);
}
// 判断是否满足模式,以及遍历到字符串末尾
return flag && (c==n);
}
}