Valid Number


Validate if a given string is numeric.

Example

"0" => true

" 0.1 " => true

"abc" => false

"1 a" => false

"2e10" => true

Example Questions Candidate Might Ask:

  • Q: How to account for whitespaces in the string?
    • A: When deciding if a string is numeric, ignore both leading and trailing whitespaces.
  • Q: Should I ignore spaces in between numbers – such as “1 1”?
    • A: No, only ignore leading and trailing whitespaces. “1 1” is not numeric.
  • Q: If the string contains additional characters after a number, is it considered valid?
    • A: No. If the string contains any non-numeric characters (excluding whitespaces and decimal point), it is not numeric.
  • Q: Is it valid if a plus or minus sign appear before the number?
    • A: Yes. “+1” and “-1” are both numeric.
  • Q: Should I consider only numbers in decimal? How about numbers in other bases such as hexadecimal (0xFF)?
    • A: Only consider decimal numbers. “0xFF” is not numeric.
  • Q: Should I consider exponent such as “1e10” as numeric?
    • A: No. But feel free to work on the challenge that takes exponent into consideration. (The Online Judge problem does take exponent into account.)

Discussion


一定要澄清问题。通过一个比较全面的例子来分析,“ -2.354 ”有三部分组成ABC, A和C都是whitespace(不单单是空格,isspace()函数判断),B是数字部分,又有四部分组成B1B2B3B4,B1和B3是符号和小数点是可选的,B2和B4是纯数字部分,不能都为空(因此需要一个indicator来判断两部分是不是都为空)。下面的代码是将B2和B4放一起来判断的,只要小数点不超过1一个就行。如果分开判断的话可以处理上面问题里最后一种情况。

Solution


class Solution {
public:
    /**
     * @param s the string that represents a number
     * @return whether the string is a valid number
     */
    bool isNumber(string& s) {
        // Write your code here
        int i = 0;
        int n = s.length();
        while(i<n && isspace(s[i])) i++; //A
        if( i<n && (s[i] == '+' || s[i] == '-')) i++; //B1
        int dotcnt = 0;
        bool hasDigit = false;
        while (i<n && !isspace(s[i])) {//B2B3B4
            if (s[i] == '.') {
                dotcnt++;
                if(dotcnt >1) //有超过一个小数点的话就false了
                    return false;
            } else if (s[i] < '0' || s[i] >'9') {
                return false;
            } else {
                hasDigit = true; //标注B2B4至少有一个存在
            }
            i++;
        }
        while(i<n) { //PART C
            if(isspace(s[i]) == false) {
                return false;
            }
            i++;
        }
        return hasDigit;
    }
};

分开处理的solution,方便扩展考虑科学计数法的情况。

class Solution {
public:
    /**
     * @param s the string that represents a number
     * @return whether the string is a valid number
     */
    bool isNumber(string& s) {
        // Write your code here
        int i = 0;
        int n = s.length();
        while(i<n && isspace(s[i])) i++;// PART A
        if( i<n && (s[i] == '+' || s[i] == '-')) i++; //B1
        int dotcnt = 0;
        bool hasDigit = false;
        while (i<n && isdigit(s[i])) { //B2
            hasDigit = true;
            i++;
        }
        if(i< n && s[i] == '.') i++; //B3
        while (i<n && isdigit(s[i])) { //B4
            hasDigit = true;
            i++;
        }
        while(i<n) { //C
            if(isspace(s[i]) == false) {
                return false;
            }
            i++;
        }
        return hasDigit;
    }
};

Update

上面搞的太复杂了,先去掉首尾字符,接下来出现的字符只能是数字/e/./+-/四种里面的一种,分析每一种出现的时候该怎么判断就行了。

class Solution {
public:
    /**
     * @param s the string that represents a number
     * @return whether the string is a valid number
     */
    bool isNumber(string& s) {
        if(s.length() ==0) return false;
        //trim the leading and trailing spaces if any
        int i=0;
        while(isspace(s[i])) {
            i++;
        }
        s.erase(s.begin(), s.begin()+i);
        if(s.length() == 0) return false;
        i = s.length()-1;
        while(isspace(s[i])) {
            s.pop_back();
        }
        if(s.length() == 0) return false;
        //start chcking, 3 cases
        //1. number
        //2. sign, + -
        //3. e  --- 1e-10
        //4. .  -- 0.2
        //some examples: 0.1 -0.1, +3.2e+10
        bool num = false;
        bool sign = false;
        bool exp = false;
        bool dot = false;
        for(int i=0; i<s.length(); i++) {//check each char in s
            char c = s[i];
            if(isdigit(c)) {
                num = true;
            } else if(c == '+' || c == '-') {
                sign = true;
                //sign can be only at 0 or after 'e'
                if(i !=0 && s[i-1] !='e') {
                    return false;
                }
            } else if(c == 'e') {
                //only can be one 'e', and there must be some number before e
                if(num==false || exp == true) {
                    return false;
                }
                exp = true;
                num = false; //make sure there must be some digit after e
            } else if(c == '.') {
                //at most one '.'
                if(dot) {
                    return false;
                }
                dot = true;
            } else {
                return false;
            }
        }
        return num; //not direct true
    }
};

results matching ""

    No results matching ""