20、表示数值的字符串

题目描述

请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。

例如,字符串 "+100","5e2","-123","3.1416" 和 "-1E-16" 都表示数值。但是 "12e","1a3.14","1.2.3","+-5" 和 "12e+4.3" 都不是。

测试用例

  • 功能测试(正数或者负数;包含或则不包含正数部分的数值;包含或者不包含小数部分的数字;包含或者不包含指数部分的数值;各种不能表达有效数值的字符串)
  • 特殊输入测试(输入字符串是空null或者空字符串)

题目考点

  • 考察应聘者对字符串的编程能力。
  • 考察应聘者分析问题的能力。而面试官希望应聘者能够从不同类型的数值中分析出规律。
  • 考察应聘者思维的全面性。在应聘者写完代码之后,面试官会期待应聘者尽量完备地想出所有可能的测试用例。

解题思路

非正则表达式解法

首先仔细表示数值的字符串的模式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 : 任意数字

参考解题

非正则表达式解法

/**
 * 表示数值的字符串
 * @Author rex
 * 2018/7/24
 */
public class Solution1 {
    /**
     * 定义str的变量的位置
     */
    private int i = 0;

    /**
     * 非正则表达式解法
     *
     * 利用模式分析为A[.[B]][e|EC]或者.B[e|EC]
     * @param str
     * @return
     */
    public boolean isNumeric(char[] str) {
        // 防止特殊输入
        if (str == null || str.length < 0) {
            return false;
        }
        // 1. 扫描A

        boolean numberic = scanInteger(str);
        // 2. 扫描B
        if (i < str.length && str[i] == '.') {
            i++;
            // 小数后面可以没有数字
            numberic = scanUnSignedInteger(str) || numberic;
        }
        // 3. 扫描C
        if (i < str.length && (str[i] == 'e' || str[i] == 'E')) {
            i++;
            // 出现e/E 后面必须跟数字
            numberic = scanInteger(str) && numberic;
        }

        return numberic && i == str.length;
    }

    /**
     * 扫描整数部分(有可能在起始处有‘+’或者‘-’)
     * @param str
     * @return
     */
    private boolean scanInteger(char[] str) {
        if (i < str.length && (str[i] == '+' || str[i] == '-')) {
            i++;
        }
        return scanUnSignedInteger(str);
    }

    /**
     * 扫描无符号整数部分(在起始处不可能有‘+’或者‘-’)
     * @param str
     * @return
     */
    private boolean scanUnSignedInteger(char[] str) {
        // 用于对比是否符合
        int temp = i;
        while (i < str.length && str[i] >= '0' && str[i] <= '9') {
            i++;
        }
        return i > temp;
    }
}
正则表达式解法
/**
 * 表示数值的字符串
 *
 * @Author rex
 * 2018/7/24
 */
public class Solution2 {
    /**
     * 正则表达式解法
     *
     * @param str
     * @return
     */
    public boolean isNumeric(char[] str) {
        // 防止特殊输入
        if (str == null || str.length < 0) {
            return false;
        }
        return new String(str).matches("[+-]?\\d*(\\.\\d+)?([eE][+-]?\\d+)?");
    }
}

 

补充

字符串选择和判断可以考虑正则表达式

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值