10

Possible Duplicate:
How to check a String is a numeric type in java

I see I can parse a String into a double by using Double.parseDouble.

Since that one might throw a NumberFormatException, and I don´t want to do programming by exception, I hesitate to put the parseDouble call into a try/catch block just to check if the string can be parsed into a double.

In Delphi, there is TryParseInt (I think), which returns a defined value (-1 I think) if the string cannot be parsed into an Integer.

There is nothing like that in Java? I mean: there is no standard way to do this?

Community
  • 1
  • 1
TheBlastOne
  • 4,291
  • 3
  • 38
  • 72
  • 2
    You could write your own if it makes you feel better, but Java doesn't have it. – James Montagne Mar 08 '12 at 14:59
  • 2
    Any return value approach will likely have cases where it can't work (for example what if your string had "-1")? Exceptions are there for a reason, in this case - *don't* avoid them... – Nim Mar 08 '12 at 14:59
  • if so necessary just create a method private boolean TryParseDouble(). Inside use try/catch + Double.parseDobule(). Make the method return false in case NFE is thrown, true otherwise. – hovanessyan Mar 08 '12 at 15:00
  • 1
    See this thread: http://stackoverflow.com/questions/1102891/how-to-check-a-string-is-a-numeric-type-in-java – rlegendi Mar 08 '12 at 15:01
  • Agree with James Montagne, this is a good example of the kind of utility methods you should include in your utility classes. – Mister Smith Mar 08 '12 at 15:11
  • 4
    @Nim I don´t avoid using exceptions. I want to avoid programming by exception. It is similar to the difference between running against the wall to find out there is a wall and checking for wall presence before you run into it. Sure, if I hit a wall, it is an exceptional unexpected stae. But if I expect walls, I´d prefer to check for them instead of banging my head jist to find them. – TheBlastOne Mar 08 '12 at 15:15
  • 1
    I'm surprised that no one mentioned [NumberUtils.createDouble](http://commons.apache.org/proper/commons-lang/javadocs/api-release/org/apache/commons/lang3/math/NumberUtils.html#createDouble%28java.lang.String%29). It returns a Double object when parsing was successful and null when the string is not a number. – Kenneth Xu May 24 '14 at 04:34
  • Sounds like what I was looking for, @KennethXu. – TheBlastOne May 27 '14 at 10:23
  • 1
    First off not sure why this is marked as duplicate, this is not asking how to check if a string is a number. it is asking for a convert method that does not throw exceptions. To that note, I think the best solution are in apache common: [toDouble](https://commons.apache.org/proper/commons-lang/javadocs/api-release/org/apache/commons/lang3/math/NumberUtils.html#toDouble(java.lang.String)), [toInt](https://commons.apache.org/proper/commons-lang/javadocs/api-release/org/apache/commons/lang3/math/NumberUtils.html#toInt(java.lang.String)) – mateuscb Apr 30 '15 at 15:51

4 Answers4

6

The standard way to do this would be:

double d;
try {
    d = Double.parseDouble(input);
}
catch (NumberFormatException e) {
    // Use whatever default you like
    d = -1.0;
}

This can of course be wrapped up as a library method if you like.

On the whole I don't miss this not being part of the language - if a string is badly formed, it doesn't represent -1 so the correct thing to do is throw an exception. If you want to treat this as -1 you're free to do so, but there's very weak rationale to make this standard library behaviour (why -1 and not 0 or NaN or null?).

Andrzej Doyle
  • 102,507
  • 33
  • 189
  • 228
  • 1
    @Moonbeam If you return `true` or `false`, how do you actually return the parsed value (unless you mean writing a method that checks if a string is parseable or not). And I'd also be hesitant to make this a library method as it stands, since how would you distinguish between `tryParseDouble("-1.0")` and `tryParseDouble("wibble")`? – Andrzej Doyle Mar 08 '12 at 15:02
  • This is the best solution. Sometimes you can bend principles like "don't program by exception". In this case, it makes sense. – aglassman Mar 08 '12 at 15:09
  • 1
    >>(why -1 and not 0 or NaN or null<< one could create a method tryParseDouble that receives the value to return if there was fauilure. I agree this is not a good solution. – TheBlastOne Mar 08 '12 at 15:13
  • @aglassman I agree though I'm not even sure this counts as bending. Presumably if your'e trying to parse a string you have good reason to believe that it represents a double (e.g. user input for "mortgage amount"), so the NFE would only be thrown in an exceptional condition. It would be worse practice to use this method speculatively on a string that simply *might* (but probably doesn't) represent a double. – Andrzej Doyle Mar 08 '12 at 16:55
  • @Andrzej You make a good point, I agree you should only do the above if you are expecting a double. – aglassman Mar 09 '12 at 14:36
4

The problem you have is that you have two possible outcomes. Either you have a valid double or you don't. If you have a return value you need to check for you might forget to check or you have an if check for every value.

try {
    double d = Double.parseDouble(input);
    double d2 = Double.parseDouble(input2);
    double d3 = Double.parseDouble(input3);
    double d4 = Double.parseDouble(input4);
    // all number are good.

} catch (NumberFormatException e) {
    e.printStackTrace(); //prints error
}

or

double d, d2, d3, d4;
if (tryParseDouble(input)) {
    d = parseDouble(input);

    if (tryParseDouble(input2)) {
        d2 = parseDouble(input2);

        if (tryParseDouble(input3)) {
            d3 = parseDouble(input3);

        } else {
            if (tryParseDouble(input4)) {
                d4 = parseDouble(input4);

            } else {
                System.out.println("Cannot parse " + input4);
            }

            System.out.println("Cannot parse " + input3);
        }

    } else {
        System.out.println("Cannot parse " + input2);
    }

} else {
    System.out.println("Cannot parse " + input);
}
gmsi
  • 1,062
  • 1
  • 16
  • 29
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • 1
    Good point. That could be "fixed" by having a boolean method tryParseDouble which receives besides the string a variable double parameter (by reference) which is set to the parsed double only if the methode returns true. However, since there is no parameter-passing by reference in Java, that second parameter would have to be a reference type. Which would be overkill. Ok, I´ll stick to the exceptional way of doing it :( – TheBlastOne Mar 08 '12 at 15:11
  • Accepted and +1´d for the good point. Thanks. – TheBlastOne Mar 08 '12 at 15:14
  • 1
    It has its own pluses and minus IMHO. If you look at Scanner for example, its has `hasNextDouble()` http://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html#hasNextDouble%28%29 – Peter Lawrey Mar 08 '12 at 15:14
  • Yeah, but having to go down using a scanner seems like overkill for such a trivial decision, if you ask me. – TheBlastOne Mar 08 '12 at 15:18
  • 1
    me too, but it depends on where your data is coming from. If you are reading a stream which you have to break into "words" anyway... – Peter Lawrey Mar 08 '12 at 15:22
1

You can always make some factory class

class DoubleFactory{

public static double tryParseDouble(final String number){

double result;
try {
    result = Double.parseDouble(number);
}
catch (NumberFormatException e) {
    result = 0.0;
}
return result;
}
}

But there is huge problem with that. Your program will continue its normal flow, but some of your model classes will be 'broken'. And after some other operation this 'default' value will pop-up, and broke other , and other. And the worst of all, you will not see the exception leading for these broken results. At least you can

catch (NumberFormatException e) {
    //add exception logging here, something like
    logger.info(e.getMessage());
    result = 0.0;
}

but the result will be the same - operations using default 0.0 (or -1.0 or whatever) value leading to some unrecoverable state.

Kiril Kirilov
  • 11,167
  • 5
  • 49
  • 74
-1

As an alternative to the solution already provided, you can use regex:

Pattern doublePattern = Pattern.compile("^\d*$");
Matcher matchesDouble = doublePattern.matcher(myString);
boolean isDouble = matchesDouble.matches();

or:

boolean isDouble = Pattern.matches("^\d*$", myString);
Andriy Budzinskyy
  • 1,971
  • 22
  • 28
  • 1
    I would agree with this solution if the task was to merely test if a list of values were in "double" format. If the code actually requires the use of the double, then you are just repeating code that the parseDouble method will do. – aglassman Mar 08 '12 at 15:12
  • 1
    @aglassman not neccessarly. It could be the Java lib exposed a worker method of parseDouble, which I would like to call directly, exception-less. I mean, other language runtimes do that, and the code duplication you mention can easily avoided this way. – TheBlastOne Mar 08 '12 at 15:21