Validate if a given string is numeric.
Some examples:
"0"
=>
true
" 0.1 "
=>
true
"abc"
=>
false
"1 a"
=>
false
"2e10"
=>
true
Note: It is intended for the problem statement to be ambiguous. You should gather all requirements up front before implementing one.
This is really a trivial question, a lot of corner cases need to be found, just like the Stirng to Integer question.
首先要明确所有可能的计数法,对于一般科学计数法和普通的计数法,能够出现的字符无非是'+', '-', '0-9', '.', 'e'
有几点很重要:
1. 数中间不能有空格
2. 正负号可以出现在数得最前端也可以出现在e之后的最前端,两部分中正负号都只能出现一次. 正负号不影响后续符号的行为
3.小数点只能出现一次,并且不能出现在e后面,并且必须要有数字存在,不能单独一个小数点。小数点出现后会影响到后续正负号,小数点后不能再出现正负号了
4. e一开始不能出现,必须在前面有数字(小数点和正负号不行)的情况下才能出现。e出现了一次以后就不能再出现了。e出现之后,会开放后续放置小数点和正负号的权限,但是由于e前后都需要数字,e出现后的hasNum标记要变为false,因为相当于后半部分又没有数字了。
5. 数字一开始标记为无,出现数字后,其会影响e的放置权限,如果出现数字并且没有e存在的情况下,那么e的放置权限开放。放入数字后就不能再出现正负号。
6. 其他一切字符出现都是false。
几种很难考虑的corner case
'.': false
'+.8e1': true
'+.8e1.1': false
'e': false
public boolean isNumber(String s) {
if (s==null ){
return false;
}
// trim off head and tail zeros which not affect result depend on question
s=s.trim();
if(s.length()==0){
return false;
}
boolean hasNum=false;
boolean canSign=true;
boolean canDot=true;
boolean canE=false;//At first we cannot put e until there is a number or other things
boolean hasE=false;
int i=0;
while(i<s.length()){
char c=s.charAt(i++);
if (c==' '){
//中间可能有空格
return false;
}
if (c=='+' ||c=='-'){
//当正负号第一次进入的时候,并且在e之前,正负号只对自身有影响,出现了以后在e出现之前就不能再出现了
if (!canSign){
return false;
}
canSign=false;
continue;
}
if (c=='.'){
if (!canDot){
return false;
}
canDot=false;//有点之后就不能再有小数点了
canSign=false;//有点之后在e出现之前都不能再有正负号了
continue;
}
if (c=='e'){
if (!canE||hasE){//When e comes, we already have e or we cannot put e, we return false
return false;
}
canE=false;//e出现之后,我们就不能再放置e了,换言之e只允许出现一次
hasE=true;//顾名思义变成true
hasNum=false;//出现e之后,之前有的是否有数字的信息清零,hasNum变false
canDot=false;//出现e之后,再也不能出现点了,所以canDot变为false
canSign=true;//出现e之后,之前是否有正负号信息清零,canSign变成true,e之后可以出现正负号
continue;
}
if (c>='0' && c<='9'){
hasNum=true;//有数字读入
//只有当有数字读入之后我们才能考虑开放e的放置权限
if (!hasE){//当放入一个数之后,如果我们处于不能放e并且现在也没有e的状态,则意味着下一个可能会放入的e将会是第一个e,所以设置canE = true表示可以放入下一个可能的e
canE=true;
}
canSign=false;//放入数字后就不能再放入符号了
}
else{
return false;
}
}
return hasNum;
}