Back to Blog
Java

Java Double parseDouble: Parsing Strings to Doubles

java double parseDouble: Learn how to use Double.parseDouble correctly, handle invalid input and edge cases like NaN and locale-specific numbers, and choose between pa...

Double parsingNumberFormatExceptionJava string conversionDouble.valueOfJava number handling
Illustration of a string being converted to a double value in Java, with a warning symbol for invalid input.

java double parseDouble requires a clear understanding of the core syntax, runtime behavior, and practical implementation patterns demonstrated in the examples below.

When you need to convert a String into a primitive double in Java, Double.parseDouble(String s) is the most direct API. It returns a primitive double, throws NumberFormatException when the input is not a valid floating-point representation, and has a few behaviors that often surprise developers. This article examines how parseDouble works, where it fails, and how to handle real-world inputs safely.

How Double.parseDouble Works

The method is a static factory on the Double wrapper class. It accepts a String and returns a primitive double. The underlying conversion uses the same rules as the Double constructor and Double.valueOf, but with a key difference: parseDouble returns a primitive, while valueOf returns a Double object (with autoboxing in most usage).

String input = "3.14159"; double value = Double.parseDouble(input); System.out.println(value); // 3.14159

The method is null-hostile: passing null throws NullPointerException, not NumberFormatException. This is a common oversight when handling user input where null might be a meaningful missing value.

String input = null; try { double value = Double.parseDouble(input); // throws NullPointerException } catch (NullPointerException e) { // handle missing input }

The valid input format follows the grammar defined by Double.valueOf. This includes leading and trailing whitespace, a leading plus or minus sign, decimal digits, an exponent part (e.g., 1.0e10), and special values NaN, Infinity, -Infinity. It does not include locale-specific decimal separators; the decimal point is always .. It also does not allow grouping separators like commas.

Handling NumberFormatException

The most common failure mode is malformed input. Any string that does not conform to the expected format triggers NumberFormatException.

String bad = "12,345.67"; try { double value = Double.parseDouble(bad); // throws NumberFormatException } catch (NumberFormatException e) { // handle invalid format }

In practice, you should wrap parsing in a try-catch whenever the input originates from external sources such as configuration files, user input, or network payloads. Ignoring the exception and assuming valid input leads to runtime failures that are hard to trace.

A more robust approach is to centralize parsing in a utility method that returns a sensible fallback or an Optional.

public static OptionalDouble parseDoubleSafely(String input) { if (input == null) { return OptionalDouble.empty(); } try { return OptionalDouble.of(Double.parseDouble(input.trim())); } catch (NumberFormatException e) { return OptionalDouble.empty(); } }

OptionalDouble is available since Java 8 and avoids the need for sentinel values like -1 or Double.MIN_VALUE.

Locale and Formatting Pitfalls

Double.parseDouble is locale-independent, which is both a strength and a trap. It always expects a dot as the decimal separator. If your application reads numbers from a locale that uses a comma, you must preprocess the input or use java.text.NumberFormat.

String localized = "3,14"; // Double.parseDouble(localized) throws NumberFormatException

To parse locale-aware numbers, you need to use NumberFormat with the appropriate Locale. This is common in financial or scientific applications where users input numbers in their local format.

import java.text.NumberFormat; import java.text.ParseException; import java.util.Locale; NumberFormat format = NumberFormat.getInstance(Locale.GERMANY); try { Number parsed = format.parse("3,14"); double value = parsed.doubleValue(); // 3.14 } catch (ParseException e) { // handle parse failure }

Note that NumberFormat.parse does not fully validate the string by default; it may accept a prefix such as 3,14abc and return 3.14. Use ParsePosition to ensure the entire string is consumed if strict validation is needed.

Special Values: NaN and Infinity

Double.parseDouble accepts the strings "NaN", "Infinity", and "-Infinity" (case-insensitive? Actually the spec allows "NaN", "Infinity", and "-Infinity" with exact case; a string like "nan" throws an exception). This is often surprising: a string like "NaN" parses successfully to a double that is not a number.

double nan = Double.parseDouble("NaN"); double posInf = Double.parseDouble("Infinity"); double negInf = Double.parseDouble("-Infinity");

The resulting double values behave according to IEEE 754. NaN compares false to everything, including itself, so you need Double.isNaN() to detect it.

double value = Double.parseDouble("NaN"); if (Double.isNaN(value)) { System.out.println("Not a number"); }

This is critical when parsing user inputs that might deliberately contain "NaN" as an error marker. If your domain does not allow such values, validate after parsing.

Double.parseDouble vs Double.valueOf

Both methods parse the same string grammar, but they differ in return type and object allocation. parseDouble returns a primitive double; valueOf returns a Double object. Historically, valueOf could return a cached instance for values in a certain range, but modern JVMs handle autoboxing efficiently enough that the difference is negligible in most applications.

MethodReturn typeTypical use
Double.parseDouble(String)double (primitive)Numeric calculations, storing in primitive arrays
Double.valueOf(String)Double (wrapper)Collections that require objects, generic APIs

When you assign the result to a primitive double, both compile to virtually identical bytecode after unboxing. Choose parseDouble for clarity when you intentionally want a primitive.

Performance and Runtime Behavior

Parsing a string to a double is not free. The parseDouble method performs lexical analysis, validates the grammar, and converts the significand and exponent to a binary fraction. This can be hundreds of nanoseconds per call. If you are parsing millions of numbers in a loop, it can become a bottleneck.

There is no faster built-in alternative in the standard library. Third-party libraries like Double.parseDouble from StringUtils or custom parsers exist, but they usually trade accuracy or compliance for speed. Before optimizing, measure whether parsing actually appears in your profiler results.

A more practical optimization is to avoid repeated parsing of the same constant strings. Cache the parsed double when the input set is fixed.

private static final double TAX_RATE = Double.parseDouble("0.19");

Static final fields ensure the parsing happens once at class load time.

Practical Decision Criteria

Choose Double.parseDouble when you need a primitive double and you can guarantee the input is in the standard format. Use Double.valueOf when you need a Double object for collections or generics. Use NumberFormat when input is locale-dependent. For extremely high-throughput custom formats, consider writing a dedicated parser, but only after profiling shows that standard parsing is a real cost.

Be explicit about how you handle null and invalid strings. A helper method that returns OptionalDouble is a clean way to avoid scattered try-catch blocks. Also, remember that Double.parseDouble accepts "NaN" and "Infinity", which may not be valid in your domain. Validate accordingly.

Edge Cases and Compatibility

Java 17 introduced a new Double.parseDouble implementation based on the java.lang.Float and java.lang.Double conversion algorithm described in the Java Language Specification. The behavior is backward compatible, but the algorithm's accuracy was improved to correctly round the shortest decimal string that converts back to the same double. This is usually transparent, but it can affect the exact double produced for very long decimal strings.

Another edge case is leading and trailing whitespace. The method trims surrounding whitespace automatically, but it does not allow internal whitespace, such as "1 000". It also does not allow as a separator? Actually whitespace includes spaces, tabs, newlines, etc., but only at the edges. Internal spaces are always invalid.

If your input may contain thousands separators, strip them explicitly before calling parseDouble.

String raw = "1,000,000.5"; String normalized = raw.replace(",", ""); double value = Double.parseDouble(normalized); // 1000000.5

This is a simple approach, but beware of locales where the comma is a decimal separator. Only strip commas if you are certain they group thousands, not decimals.

Final Technical Consideration: Rounding to a Shortest String

When you parse a decimal string that has more digits than a double can represent exactly, the parser rounds to the nearest representable double. This rounding is the same as in Double.valueOf. The exact result depends on the binary representation of the double, which is documented by the IEEE 754 standard. As a developer, you cannot predict the exact binary fraction without converting, so do not assume that Double.parseDouble("0.1") gives a mathematically precise decimal 0.1. It gives the nearest binary double, which is 0.1000000000000000055511151231257827.

When comparing parsed doubles, avoid == with literals. Use an epsilon comparison or Double.compare with a tolerance. For complete accuracy, consider BigDecimal when you need decimal precision.

java double parseDouble: Practical Usage and Code Examples | RYUSLOG DEV