1

I know that easily I can use a try/catch to check command line arguments are a double.

I'm seeking a way to check this without using a costly try/catch block. I'm fairly new to Java. I'ved searched a few forums but haven't found anything specific to my issue.

System.out.println(Double.parseDouble(args[1]));

^^This will cause an error. besides putting this in a try/catch can someone point me towards data validation that will prevent this? assume args[1] is a string of text.

6
  • 3
    Just use a try/catch NumberFormatException. Is not that costly (who told you that?) and besides, the validation rules for determining what's a valid double value can be quite complex to implement Commented Sep 23, 2013 at 15:06
  • stackoverflow.com/questions/1102891/… Commented Sep 23, 2013 at 15:06
  • Related: stackoverflow.com/q/8362027/1065197 Commented Sep 23, 2013 at 15:06
  • How many times do you run that statement? Is it a proven bottleneck? If not, then you should definitely go with the tested and true try/catch solution. Remember: premature optimization is the root of all evil. Commented Sep 23, 2013 at 15:07
  • Use try/catch like everybody else. Commented Sep 23, 2013 at 15:14

4 Answers 4

5

The try-catch approach is the generally accepted way to do this, primarily because there are actually a lot of formats a valid double can have:

double a = 42.e10;  // or 42.E10
double b = 42.f;    // or 42.F
double c = 42.d;    // or 42.D
double d = 010E010D;
double e = 0x1.fffffffffffffP+1023;
double f = 0x1.0p-1022;

All of these are valid doubles and can be parsed from a string via parseDouble(). Double.parseDouble("NaN") and Double.parseDouble("Infinity") are also valid (although NaN and Infinity aren't literals). Not to mention parseDouble() also deals with leading or trailing whitespaces. So my answer is: don't! Use the try-catch approach. It is possible to construct a regex that matches some subset of (or maybe even all) valid double formats, but I doubt that will actually be more efficient than catching and handling a NumberFormatException.


A full regex is actually explained in the documentation of valueOf():

To avoid calling this method on an invalid string and having a NumberFormatException be thrown, the regular expression below can be used to screen the input string:

  final String Digits     = "(\\p{Digit}+)";
  final String HexDigits  = "(\\p{XDigit}+)";
  // an exponent is 'e' or 'E' followed by an optionally
  // signed decimal integer.
  final String Exp        = "[eE][+-]?"+Digits;
  final String fpRegex    =
      ("[\\x00-\\x20]*"+  // Optional leading "whitespace"
       "[+-]?(" + // Optional sign character
       "NaN|" +           // "NaN" string
       "Infinity|" +      // "Infinity" string

       // A decimal floating-point string representing a finite positive
       // number without a leading sign has at most five basic pieces:
       // Digits . Digits ExponentPart FloatTypeSuffix
       //
       // Since this method allows integer-only strings as input
       // in addition to strings of floating-point literals, the
       // two sub-patterns below are simplifications of the grammar
       // productions from section 3.10.2 of
       // The Java™ Language Specification.

       // Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt
       "((("+Digits+"(\\.)?("+Digits+"?)("+Exp+")?)|"+

       // . Digits ExponentPart_opt FloatTypeSuffix_opt
       "(\\.("+Digits+")("+Exp+")?)|"+

       // Hexadecimal strings
       "((" +
        // 0[xX] HexDigits ._opt BinaryExponent FloatTypeSuffix_opt
        "(0[xX]" + HexDigits + "(\\.)?)|" +

        // 0[xX] HexDigits_opt . HexDigits BinaryExponent FloatTypeSuffix_opt
        "(0[xX]" + HexDigits + "?(\\.)" + HexDigits + ")" +

        ")[pP][+-]?" + Digits + "))" +
       "[fFdD]?))" +
       "[\\x00-\\x20]*");// Optional trailing "whitespace"

  if (Pattern.matches(fpRegex, myString))
      Double.valueOf(myString); // Will not throw NumberFormatException
  else {
      // Perform suitable alternative action
  }

As you can see it's somewhat of a nasty regex.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for the responses. I was really just looking on how it would work to validate without using the try/catch. More for informational knowledge rather than implementation.
@user2807730 Well the regex is the only other sane approach I can think of. In any case, don't forget to accept an answer if any worked for you.
if (args[1].hasNextDouble()){ System.out.println(Double.parseDouble(args[1])); } ^^Will this not work? I wonder because no one suggested it.
@user2807730 No (assuming args is a string array) because strings don't have a hasNextDouble() method.
1

As commenter Óscar López says, just use a try/catch block and catch NumberFormatException. This is the right way to ensure that the target string is a properly formatted double and the potential overhead of the try/catch construct is worth the correctness and clarity of the program.

Double d = null;
try {
  d = Double.parseDouble(args[1]);
} catch (NumberFormatException nfe) {
  // TODO
}

Comments

1

Java has no method like isDouble or isNumeric out of the box, But you could write them on your own:

public static boolean isDouble(String s) {
    try {
        Double.parseDouble(s);
    } catch (NumberFormatException e) {
        return false;
    }
    return true;
}

But double has many ways to be writen it:

  • 23.2
  • 23f
  • 23e10
  • 2_3.4_5 (cannot be parsed with Double#parseDouble(String))
  • 2_3E1_0d (cannot be parsed with Double#parseDouble(String))

If you just want to check for the XX.XXX pattern this is the way to go using RegEx:

public static boolean isDoubleDigits(String s) {
    return s.matches("\\d+(\\.\\d{1,2})?");
}

1 Comment

The _s actually don't work with parseDouble(), even though they are valid in a double literal as of Java 7.
0

Why not use a framework for command-line input validation? Checkout Apache Commons CLI project

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.