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.
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.
Sources
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.
Worked example
Take 42, the first case in the tester. Reading the pattern left to right, each part takes its share of the text:
^The start of the text (matches a position, no characters)[+-]?Optionally one character: “+” or “-” (matches a position, no characters)(?:\d+(?:\.\d*)?|\.\d+)A group (not captured), either of two alternatives: matches 42(?:[eE][+-]?\d+)?A group (not captured), optional (zero or one time): (matches a position, no characters)$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.
| Text | Result | Why |
|---|---|---|
| 42 | Passes | a whole number |
| -17 | Passes | negative |
| +3.14 | Passes | explicit plus sign and decimals |
| .5 | Passes | no digit before the point |
| 5. | Passes | no digit after the point |
| 6.022e23 | Passes | scientific notation |
| -1.6E-19 | Passes | capital E and a negative exponent |
| 007 | Passes | leading zeros pass here, though JSON forbids them |
| . | Fails | a point with no digits |
| - | Fails | a sign alone |
| 1.2.3 | Fails | two decimal points |
| 1e | Fails | an exponent with no digits |
| 1,000 | Fails | thousands separators aren’t accepted |
| 0x1F | Fails | hexadecimal notation |
| 42 | Fails | a 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.
| Flavour | Pattern | Notes |
|---|---|---|
| Python | (?a)^[+\-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+\-]?\d+)?\Z | Python'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+)?\z | In .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.