Reputation: 1785
I'm trying to ensure that a given string is a valid double. Most answers to this sort of question suggest using Double.parseDouble(inputString)
. However this isn't as robust as I'd hope. For instance if I enter a String such as "1one" Double.parseDouble("1one")
will output "1" as opposed to returning an exception for an invalid double.
I've tried to get around this by iterating over the string and ensuring that every number is a digit:
for (int i = 0; i < number.length(); i++) {
previousChar = number.charAt(i);
if (!Character.isDigit(number.charAt(i))
&& number.charAt(i) != '.'
&& number.charAt(i) != ',') {
return null;
}
}
But for cases such as "20..02" or "20,,02" this will simply return 20. I was wondering what the best way to account for cases such as these would be.
Upvotes: 1
Views: 142
Reputation: 12751
Good question. Depending on the users, you may need to be careful of differences between locales. Some places use ,
as a thousand separator others as a decimal point. You can find the locale-specific value using:
DecimalFormat formatter = (DecimalFormat) NumberFormat.getInstance();
DecimalFormatSymbols symbols = formatter.getDecimalFormatSymbols();
char decimalSeparator = symbols.getDecimalSeparator();
I would suggest writing a regular expression for your exact requirement rather than doing the matching manually. Remember to escape .
if you want it to match .
and not "any character".
Alternatively, you may be able to use parseDouble
which does seem to throw an exception for "1one"
after all:
System.out.println(Double.parseDouble("1one"));
For me, it produces:
Exception in thread "main" java.lang.NumberFormatException: For input string: "1one"
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1241)
at java.lang.Double.parseDouble(Double.java:540)
Upvotes: 3
Reputation: 356
Using a simple regex, you can check if it contains any non numerical characters like so:
String input = "1one2";
String numerical = input.replaceAll("[^0-9.]", "");
if (input.equals(numerical)) // If you remove all non numbers, still the same string
After which you can parse it for a double.
Upvotes: -2
Reputation: 33273
I would use Double.parseDouble
, because, contrary to what you believe, it does throw a NumberFormatException
for 1one
.
public class k {
public static void main(String argv[]) {
double d = Double.parseDouble("1one");
}
}
Output:
Exception in thread "Main Thread" java.lang.NumberFormatException: For input string: "1one"
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1222)
at java.lang.Double.parseDouble(Double.java:510)
at k.main(k.java:3)
If I wanted to allow both ,
and .
and not just the decimal point specified by the locale, I would replace
any ,
and .
with the locale specified decmial point.
Upvotes: -1
Reputation: 234715
Parsing strings to doubles is fraught with danger. For example, in France, 1,234 is a number just a little greater than 1. They use .
to separate round thousands and ,
to denote the start of the decimal portion.
The best way to check if a string is a valid number is to use NumberFormat
to attempt to parse it and treat any exceptions thrown as an indication that the string is not a valid number. NumberFormat
allows you to associate a locale:
NumberFormat nf = NumberFormat.getInstance(Locale.FRENCH/*for example*/);
double myNumber = nf.parse(myString); /*will throw an exception if not valid*/
Upvotes: 0
Reputation: 565
You could use the Validator framework and use the DoubleValidator from commons-validator.
DoubleValidator validator = DoubleValidator.getInstance();
validator.validate("1one");
Upvotes: 1