一、题目
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100"、“5e2”、"-123"、“3.1416”、"-1E-16"、“0123"都表示数值,但"12e”、“1a3.14”、“1.2.3”、"±5"及"12e+5.4"都不是。
二、解决
1、正则表达式
补充:待完善,case “e9” 结果错误。
public class Solution {
public boolean isNumeric(char[] str) {
String string = String.valueOf(str);
return string.matches("[\\+\\-]?\\d*(\\.\\d+)?([eE][\\+\\-]?\\d+)?");
}
}
/*
以下对正则进行解释:
[\\+\\-]? -> 正或负符号出现与否
\\d* -> 整数部分是否出现,如-.34 或 +3.34均符合
(\\.\\d+)? -> 如果出现小数点,那么小数点后面必须有数字;
否则一起不出现
([eE][\\+\\-]?\\d+)? -> 如果存在指数部分,那么e或E肯定出现,+或-可以不出现,
紧接着必须跟着整数;或者整个部分都不出现
*/
2、常规思路
思路:
分类标准:A.BeC或A.BEC。
处理逻辑:对输入字符串从左到右,按顺序判断是否包含这三部分。
- 在字符串后添加结束标志;
- scanInteger():扫描有符号整数,用来匹配A和C部分;
- scanUnsignedInteger():扫描无符号整数,用来匹配B部分。
注意:输入用例中,字符串首尾空格合法,如“空格1.2空格”是返回true的。所以跳过首尾空格。
代码:
class Solution {
private int pos = 0;
public boolean isNumber(String s) {
// 空字符串
if (s == null || s.length() == 0) return false;
// 添加结束标志
s = s + '|';
// 1、首部空格
while (s.charAt(pos) == ' ') pos++;
// 2、整数部分
boolean num = scanInt(s);
// 3、小数部分:小数点及无符号整数
if (s.charAt(pos) == '.') {
pos++;
// 注意scanUnsignedInteger要在前面,否则不会扫描小数点后面的整数。因为||有断路功能,前面为true,后面不计算,这个会影响pos指针的移动。进而影响最后返回时最后一个字符不一定为 |
// 如“0.8” return false,正确是true。
// 处理小数部分,用 || 原因:
// 1. 小数没整数部分,如.123等于0.123
// 2. 小数点后面可以没有数字,如233.等于233.0
// 3. 小数点前后都有数字
num = scanUnsignedInt(s) || num;
}
// 4、指数部分
if (s.charAt(pos) == 'E' || s.charAt(pos) == 'e') {
pos++;