Back to Blog
Java

Java Double.parseDouble: Parsing Strings to Doubles

See how to use Double.parseDouble to convert strings to primitive doubles, handle invalid input and locale-specific numbers, and choose between parseDouble and valueOf.

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.

Converting a String into a primitive double in Java is usually done with Double.parseDouble(String s). It returns a primitive double, throws NumberFormatException for invalid input, and has a few behaviors that often surprise developers. This article explains how parseDouble works, where it fails, and how to handle real-world inputs safely.

How Double.parseDouble Works

Double.parseDouble is a static method on the Double wrapper class. It accepts a String and returns a primitive double. The conversion rules are the same as those used by Double.valueOf, but the return types differ: parseDouble returns a primitive, while valueOf returns a Double object.

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

Passing null throws NullPointerException, not NumberFormatException. This matters when handling user input where null might represent a missing value.

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

The accepted format is the grammar used by Double.valueOf: optional leading or trailing whitespace, an optional leading sign, decimal digits, an optional decimal point, an optional exponent such as 1.0e10, and the special values NaN, Infinity, and -Infinity. Locale-specific decimal separators are not accepted; the decimal point is always .. Grouping separators such as commas are not accepted either.

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, wrap parsing in a try-catch whenever the input comes 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 an OptionalDouble or a sensible fallback.

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 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, preprocess the input or use java.text.NumberFormat.

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

To parse locale-aware numbers, 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 exact strings "NaN", "Infinity", and "-Infinity". They are case-sensitive, so "nan" or "infinity" throw NumberFormatException. This often surprises developers: a string like "NaN" parses successfully into 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 use Double.isNaN() to detect it.

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

This is important 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 return different types. parseDouble returns a primitive double; valueOf(String) returns a Double object. Choose based on whether you need a primitive or an object for collections or generic APIs. Unlike Integer.valueOf, Double.valueOf does not provide a meaningful cache for arbitrary floating-point values, so there is no performance reason to prefer one over the other for primitive use.

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 both results to a primitive double, autounboxing produces the same numeric value. Use parseDouble for clarity when you intentionally want a primitive.

Performance and Runtime Behavior

Parsing a string to a double is not free. The method validates the string and then converts the significand and exponent to a binary double. If you parse millions of numbers in a loop, the cost can matter, but exact timings depend on the JVM, input format, and hardware. Profile before optimizing.

The standard library does not provide a separate high-throughput parser. A custom parser for a restricted input format may be faster, but it must handle all valid forms and edge cases accurately. Before writing one, measure whether parsing actually appears in your profiler.

A useful optimization is to avoid reparsing fixed constants:

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 very high-throughput custom formats, consider a dedicated parser 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

Leading and trailing whitespace is allowed and ignored. Internal whitespace is not allowed, so a string like "1 000" is invalid. Tabs and newlines at the edges are treated as whitespace, but whitespace between digits is 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.

Rounding to the Nearest Double

When a decimal string has more digits than a double can represent exactly, parsing rounds to the nearest representable binary value. The exact result is determined by IEEE 754 rules and cannot be reliably predicted from the decimal text alone. For example, Double.parseDouble("0.1") does not return a mathematical decimal 0.1; it returns the closest binary double, approximately 0.1000000000000000055511151231257827.

When comparing parsed doubles, avoid relying on == with a literal. Use an epsilon comparison when you need approximate equality, and consider BigDecimal when you need exact decimal precision.

Java Double.parseDouble: Usage, Edge Cases, and Code Examples | RYUSLOG DEV