Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Most elegant way to detect if a String is a number?

Is there a better, more elegant (and/or possibly faster) way than

boolean isNumber = false;
try{
   Double.valueOf(myNumber);
   isNumber = true;
} catch (NumberFormatException e) {
}

...?


Edit: Since I can't pick two answers I'm going with the regex one because a) it's elegant and b) saying "Jon Skeet solved the problem" is a tautology because Jon Skeet himself is the solution to all problems.

like image 388
Epaga Avatar asked Dec 11 '08 14:12

Epaga


People also ask

How do you tell the difference between a string and a number?

The differences between the Integer and String objects in Java are: Integer can be converted to String, but String cannot be converted to Integer. Integer is a numeric value, while String is a character value represented in quotes.

How do you check if a string is a number JS?

Use the isNaN() Function to Check Whether a Given String Is a Number or Not in JavaScript. The isNaN() function determines whether the given value is a number or an illegal number (Not-a-Number). The function outputs as True for a NaN value and returns False for a valid numeric value.


1 Answers

I don't believe there's anything built into Java to do it faster and still reliably, assuming that later on you'll want to actually parse it with Double.valueOf (or similar).

I'd use Double.parseDouble instead of Double.valueOf to avoid creating a Double unnecessarily, and you can also get rid of blatantly silly numbers quicker than the exception will by checking for digits, e/E, - and . beforehand. So, something like:

public boolean isDouble(String value)
{        
    boolean seenDot = false;
    boolean seenExp = false;
    boolean justSeenExp = false;
    boolean seenDigit = false;
    for (int i=0; i < value.length(); i++)
    {
        char c = value.charAt(i);
        if (c >= '0' && c <= '9')
        {
            seenDigit = true;
            continue;
        }
        if ((c == '-' || c=='+') && (i == 0 || justSeenExp))
        {
            continue;
        }
        if (c == '.' && !seenDot)
        {
            seenDot = true;
            continue;
        }
        justSeenExp = false;
        if ((c == 'e' || c == 'E') && !seenExp)
        {
            seenExp = true;
            justSeenExp = true;
            continue;
        }
        return false;
    }
    if (!seenDigit)
    {
        return false;
    }
    try
    {
        Double.parseDouble(value);
        return true;
    }
    catch (NumberFormatException e)
    {
        return false;
    }
}

Note that despite taking a couple of tries, this still doesn't cover "NaN" or hex values. Whether you want those to pass or not depends on context.

In my experience regular expressions are slower than the hard-coded check above.

like image 78
Jon Skeet Avatar answered Sep 18 '22 22:09

Jon Skeet