# ES proposal: numeric separators

The proposal “Numeric Separators” by Sam Goto and Rick Waldron is currently at stage 3. This blog post explains how it works.

## What are numeric literals?  #

JavaScript has several numeric literals:

• Decimal literals: `123.45`, `86`, `12e-5`
• Binary integer literals: `0b1011`
• Octal integer literals: `0o765`
• Hexadecimal integer literals: `0x2FF`

Interestingly, unary minus (`-`) is an operator and not part of numeric literals (apart from signed exponents in decimal literals).

## Grouping digits in numeric literals  #

Grouping digits to make long numbers more readable has a long tradition. For example:

• At the end of 2016, Munich has 1,464,301 inhabitants.
• The distance between Earth and Sun is 149,600,000 km.

The proposal allows underscores as separators in numeric literals:

``````const inhabitantsOfMunich = 1_464_301;
const distanceEarthSunInKm = 149_600_000;
``````

With other bases, grouping is important, too:

``````const fileSystemPermission = 0b111_111_000;
const bytes = 0b1111_10101011_11110000_00001101;
const words = 0xFAB_F00D;
``````

You can also use the separator in fractions and exponents:

``````const massOfElectronInKg = 9.109_383_56e-31;
const trillionInShortScale = 1e1_2;
``````

## Restrictions  #

The key restriction to keep in mind is: You can only put underscores between two digits. Therefore, the following numeric literals are illegal.

``````3_.141
3._141

1_e12
1e_12

_1464301  /* valid variable name! */
1464301_

0_b111111000
0b_111111000
``````

Furthermore, you can never use more than one underscore in a row:

``````123__456 /* two underscores – not allowed */
``````

The motivation behind these restrictions is to keep things simple.

## BigInts and numeric separators  #

The proposed arbitrary-precision integers (BigInts) enable you to represent larger numbers numerically. Thus, numeric separators are especially helpful with them:

``````const massOfEarthInKg = 6_000_000_000_000_000_000_000_000n;
``````

BigInts are often used to represent money in the financial technical sector. Separators can help here, too:

``````const priceInCents = 123_000_00; // 123 thousand dollars
``````

## Parsing numbers with separators  #

The following functions for parsing numbers will not support separators:

• `Number()`
• `parseInt()`
• `parseFloat()`

For example:

``````> Number('123_456')
NaN
> parseInt('123_456')
123
``````

The rationale is that numeric separators are for code. Other kinds of input should be processed differently.

### A helper function for parsing numbers with separators  #

One technique for parsing numbers with separators is to remove non-digit characters:

``````const RE_NON_DIGIT = /[^0-9]/gu;
function removeNonDigits(str) {
str = str.replace(RE_NON_DIGIT, '');
return Number(str);
}
``````

This is how you use this function:

``````> removeNonDigits('149,600,000')
149600000
> removeNonDigits('1,407,836')
1407836
``````

## Tips  #

### Don’t forget about exponential notation  #

With trailing zeros, exponential notation may be more convenient than grouping zeros. Compare:

``````const timeoutInMilliseconds = 10e3; /* 10 seconds */
const tenSecondTimeout = 10_000; /* 10 seconds */
``````

### Numbers aren’t always the best choice to represent numeric(ish) data  #

Some data such as phone numbers, credit card numbers and social security numbers, are in some ways numbers, in others not: There may be non-numeric prefixes and separators and leading digits are significant. They should also never be represented in exponential notation.

Therefore – avoid:

``````// Don’t do this:
const phoneNumber = 555_2368;
const creditCardNumber = 378_2822_4631_0005;
const socialSecurityNumber = 111_11_1111;
``````