Skip to content

Number Regex: Integers, Decimals and Exponents

Accept a whole or decimal number with an optional plus or minus sign and an optional exponent, the way people and most programming languages write them.

JavaScript
68 characters

One case per line; the m flag makes ^ and the end anchor work line by line.

Link optionspattern only

The address bar holds the pattern, flags and replacement, so Copy link shares them. Your test text stays out of it unless you include it (up to 2,000 characters), because it may be private. Nothing is sent to a server.

Matches

8matches

The first is “42”, at position 0.

Groups
none
Characters matched
33 of 68
What the pattern meansHover or tap a part to see it in the pattern and what it matched
How this works: Method, 5 sources, Checked against 1 worked example,

How this works

Method

Your pattern runs in your own browser’s JavaScript engine, in a background worker that is stopped after 1.5 seconds, so a pattern that backtracks catastrophically can’t freeze the page. The explanation comes from our own parser of the ECMAScript pattern grammar, checked against the engine; what each part matched is found by wrapping that part in one more group and running the pattern again. Conversions to other flavours only rewrite the syntax and list what their documentation says works differently.

How it’s tested

One worked example for this page is checked by automated tests before every release: given the inputs, the tool must show the expected answer.

Changes

  • First published, with a library of 19 common patterns and their test cases.

How we make toolsReport a mistake

Worked example

Take 42, the first case in the tester. Reading the pattern left to right, each part takes its share of the text:

  1. ^The start of the text (matches a position, no characters)
  2. [+-]?Optionally one character: “+” or “-” (matches a position, no characters)
  3. (?:\d+(?:\.\d*)?|\.\d+)A group (not captured), either of two alternatives: matches 42
  4. (?:[eE][+-]?\d+)?A group (not captured), optional (zero or one time): (matches a position, no characters)
  5. $The end of the text (matches a position, no characters)

How the number regex works

\[+-]?\ allows one optional sign. Then comes the main body, an alternation of two shapes. \\d+(?:\.\d*)?\ is digits, optionally followed by a point and any number of digits, which covers 42, 3.14 and 5. The other branch, \\.\d+\, covers numbers that start with the point, like .5. Splitting it this way guarantees at least one digit somewhere, so "." and "-" fail.

The exponent \(?:[eE][+-]?\d+)?\ is optional: an e or E, an optional sign, and at least one digit. That lets 6.022e23 and 1.6E-19 through and stops "1e" with nothing after it. Every quantifier here works on a different kind of character (digits, then a point, then e), so the regex never has two ways to match the same text and stays fast even on very long inputs.

It's worth knowing how this differs from JavaScript's own conversion. \Number()\ ignores surrounding spaces, turns an empty string into 0, and reads "0x1F" as 31, while \parseFloat("3.5abc")\ happily returns 3.5. Testing with the regex first means only clean numbers reach those functions. JSON is stricter again: no leading plus, no leading zeros, and digits on both sides of the point, so "007", "+1", ".5" and "5." all pass here but are not valid JSON numbers.

  • JSON numbers allow a leading minus but no leading plus, and leading zeros are not allowed; Infinity and NaN are not permitted. Source: RFC 8259, section 6.
  • When JavaScript converts a string with Number(), surrounding whitespace is ignored, an empty string becomes 0, and 0x, 0b and 0o prefixes are read as hex, binary and octal. Source: MDN: Number, number coercion.

Test cases

Every case runs as an automated test of this page’s pattern, so the table can’t drift from what the pattern really does.

Test cases for the Number regex
TextResultWhy
42Passesa whole number
-17Passesnegative
+3.14Passesexplicit plus sign and decimals
.5Passesno digit before the point
5.Passesno digit after the point
6.022e23Passesscientific notation
-1.6E-19Passescapital E and a negative exponent
007Passesleading zeros pass here, though JSON forbids them
.Failsa point with no digits
-Failsa sign alone
1.2.3Failstwo decimal points
1eFailsan exponent with no digits
1,000Failsthousands separators aren’t accepted
0x1FFailshexadecimal notation
42Failsa leading space

What it doesn’t check

  • It doesn’t accept thousands separators or a decimal comma, so 1,000 and 3,14 fail; normalise locale formats first.
  • Infinity, NaN, hexadecimal, binary and numeric separators like 1_000 are rejected, though JavaScript accepts some of them elsewhere.
  • Passing the regex doesn’t guarantee the value fits in a double: 1e400 matches and becomes Infinity.
  • For whole numbers only, use the simpler \^[+-]?\d+\ with the end anchor.

The same pattern in other languages

Converted automatically from the JavaScript version; the tester above always runs JavaScript.

The pattern in Python, PCRE, Go, Java and .NET
FlavourPatternNotes
Python(?a)^[+\-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+\-]?\d+)?\ZPython's \d matches any Unicode decimal digit in str patterns, so "٤٢" would pass; use [0-9] or re.ASCII to limit it to 0–9. Python's float() accepts those digits too.
PCRE^[+\-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+\-]?\d+)?\z
Go^[+\-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+\-]?\d+)?$
Java^[+\-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+\-]?\d+)?\z
.NET^[+\-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+\-]?\d+)?\zIn .NET, \d and \w match any Unicode digit or letter. Pass RegexOptions.ECMAScript, or write [0-9] and [A-Za-z0-9_], for JavaScript’s ASCII-only meaning.

Sources

Frequently Asked Questions

How do I match only whole numbers?

Drop the decimal and exponent parts: an optional sign followed by one or more digits, anchored at both ends. Add a length limit if the value must fit a fixed-size integer.

Why not just use Number() or parseFloat()?

Both accept inputs you may not want. Number turns an empty string into 0 and reads hex, and parseFloat stops at the first bad character and returns what it has. A regex check first makes sure the whole string is a number.

How do I allow commas as thousands separators?

Either remove the commas before testing, or use a pattern for groups of three digits separated by commas. Removing them is simpler and works for any grouping.

Does this match JSON numbers exactly?

No, it is a little more relaxed: it allows a plus sign, leading zeros and a point with digits on one side only. JSON allows none of those.