Modern Javascript Recap - Part III

Joris Verbogt
Joris Verbogt
Apr 15 2022
Posted in Engineering & Technology

How to compare and format numbers

Modern Javascript Recap - Part III

Since the introduction of modern JavaScript with ES5 and later ES6, common language patterns and structures were introduced that lifted the limited expressive power of the original JavaScript language to the level of more robust programming languages.

In the first part of this blog post, I touched on Map and Set, in the second part I discussed iterators and collections. In the third part, I will take a look at what seems a basic data type: numbers.

Numerical Precision

Numerical values are represented in JavaScript by the Number type, which is used for both integer and floating point data. Since the early days of JavaScript, numbers have been a source of confusion and common error, because behaviour depends on low-level binary floating point implementation details.

Because of the binary nature of computers, floating point values are combinations of powers of 2, which means they are often only an approximation of decimal fractions. For example, if you want to check if 2 numbers add up to a value:

let a = 0.1
let b = 0.2
let c = 0.3
a + b === c // false!

Because these numbers are internally represented as a binary floating point value, in this case there is a tiny fraction of a difference. In fact the result of '0.1 + 0.2' is actually more like 0.30000000000000004. To make sure numbers are 'equal', or, to be more precise, the difference between numbers is 0, you actually need to check if the difference is smaller than the smallest representable difference. In ES6, a new constant was introduced, Number.EPSILON, which is equal to 2^-52 and can be thought of as the margin of error between the decimal number and its binary floating point representation.

So, to correctly compare numbers, the above example would need to be:

let a = 0.1
let b = 0.2
let c = 0.3
a + b - c < Number.EPSILON // true!

This is also useful when correctly rounding numbers to fixed decimal precision:

let price = 5.015
Math.round(price * 100) / 100 // 5.01

Math.round(price * 100 * (1 + Number.EPSILON)) / 100 // 5.02

Number Validity Checking

ES6 introduced 2 useful methods. The first one is isNaN, which is used to check if a value is a valid number:

Number.isNaN(42) // false
Number.isNaN('42') // false
Number.isNaN('fortytwo') // true
Number.isNaN(Math.sqrt(-1)) // true
Number.isNaN(NaN) // true

The second one is to see if a number is finite or infinite:

Number.isFinite(42) // true
Number.isFinite(2 / 0) // false
Number.isFinite(Infinity) // false
Number.isFinite(NaN) // false

Number Formatting

Although numbers are mostly used internally in code to perform arithmetic on data, eventually there will be a visual display of the result. The way numbers are formatted differs between countries and cultures, so localization needs to be applied before they are actually displayed.

ES6 introduced the Intl module, which takes care of digit grouping and separators:

let localeUS = new Intl.NumberFormat('en-US')
let localeNL = new Intl.NumberFormat('nl-NL')
let data = 12345.678
localeUS.format(data) // 12,345.678
localeNL.format(data) // 12.345,678

Also, since numerical data is often related to monetary values, the Intl module also allows for the correct display of currencies:

var localeUS = new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" })
var localeNL = new Intl.NumberFormat("nl-NL", { style: "currency", currency: "EUR" })
var localeFR = new Intl.NumberFormat("fr-FR", { style: "currency", currency: "EUR" })
let data = 42000.42
localeUS.format(data) // $42,000.42
localeNL.format(data) // € 42.000,42
localeFR.format(data) // 42 000,42 €

Conclusion

Dealing with numbers is a challenge in any programming language, but especially so in JavaScript since it only has a very bare-bones Number data type. The examples above show you how to prevent common errors and how to simplify the visualization of numeric data in any language out of the box!

As always, we hope you liked this article and if you have anything to add, maybe you are suited for a Developer position in Notificare. We are currently looking for a Core API Developer, check out the job description. If modern Javascript is your thing, don't hesitate to apply!

Keep up-to-date with the latest news