DEV Community

Cover image for How to do magic with Numbers

Posted on • Updated on • Originally published at

How to do magic with Numbers

JavaScript Number type would have been called double or float64 in a compiled language. Therefore, numbers have some limits:

const maxInt = Number.MAX_SAFE_INTEGER // 9007199254740991
const minInt = Number.MIN_SAFE_INTEGER // -9007199254740991
minInt === -maxInt // true
const maxDouble = Number.MAX_VALUE // 1.7976931348623157e+308
const minDouble = Number.MIN_VALUE // -1.7976931348623157e+308
Enter fullscreen mode Exit fullscreen mode

See that strange long number in min and max values? That is the first magical way of representing a JavaScript number: using a base and an exponent (a.k.a beN):

const minusTwo = -2e0 // -2
const one75 = 175e-2 // 1.75
Enter fullscreen mode Exit fullscreen mode

In practice, you specify a base number, then write e and specify where you want to move the dot. If the last number is positive - you'll be adding zeros, if negative - you'll be moving the dot to the left:

const zero = 0e0 // 0; move dot from 0.0 zero times
const zero5 = 5e-1 // 0.5; move dot from 5.0 one time left
const fifty = 5e1 // 50; move dot from 5.0 one time right
const alsoFifty = 5e+1 // 50
const minusFifty = -5e+1 //-50; move dot from -5.0 one time right
const seventeen5 = 1.75e1 // 17.5; move dot from 1.75 one time right
Enter fullscreen mode Exit fullscreen mode

But, this representation may be a bit hard to read, so you can also use old plain decimals with the underscore as a separator:

const million = 1_000_000; //1000000
const fiveK = 5_000 // 5000
const justLoveUnderscores = 1_2_3.3_2_1 //123.321

const oops = 1__0 // Error: Only one underscore is allowed as numeric separator
const nope = 0_1 // Error: Numeric separator can not be used after leading 0
Enter fullscreen mode Exit fullscreen mode

Dealing with binary numbers instead? No worries, you can write it like this:

const five = 0b101 // 5
const alsoFive = 0B101 // 5; `b` is case tolerant
const max8bit = 0b1111_1111 // 255; You can use separators in any number :-)
const lessFive = -0b0101 // -5
Enter fullscreen mode Exit fullscreen mode

Of course, hexadecimal numbers are also a must-have in your arsenal:

const max8bit = 0xff // 255
const hexNum = -0xabc // -2748
const max32bit = 0xffff_ffff // 4294967295; can use separators
Enter fullscreen mode Exit fullscreen mode

And, just so you know, ECMA Script 2015 introduced octals:

const maxBit = 0o7 // 7
const eight = 0o10 // 8
const funnyZero = 0O0 // 0
Enter fullscreen mode Exit fullscreen mode

If so happens and you can't squeeze your integer number in 64bits, you can convert it to BigInt by adding an n to it:

const maxDouble = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff // Infinity
const biggerThanMaxDouble = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffn // 179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137215n

const bigTen = 10n // 10n;
const bigLess50 = -50n // -50n
Enter fullscreen mode Exit fullscreen mode

And, there are several truly magic numbers in JavaScript:

Infinity === Number.POSITIVE_INFINITY // true
-Infinity === Number.NEGATIVE_INFINITY // true
const smallestFraction = Number.EPSILON // 2.2204460492503130808472633361816e-16
smallestFraction === Math.pow(2, -52) // true
Enter fullscreen mode Exit fullscreen mode

As everyone has that weird cousin, JavaScript numbers have a special number that is literally not a number.

NaN value is a special value, and every single operation with it will result in NaN, including comparison:

NaN === Number.NaN // false !!
Number.isNaN(NaN) // true

NaN + 1 // NaN
NaN * 15 // NaN
NaN / NaN // NaN
1 * NaN // NaN
Enter fullscreen mode Exit fullscreen mode

The most convinient way to make a NaN is through a failed type conversion:

parseInt('abc') // NaN
parseInt({}) // NaN
parseFloat('1.1.1') // NaN
'abc' * 1 // NaN
new Number('abc') // Number {NaN}
Enter fullscreen mode Exit fullscreen mode

However, there are built-in functions to help you deal with edge cases and NaN:

Number.isNaN(123) // false
Number.isNaN('abc') // true
Number.isNaN(NaN) // true

Number.isFinite(123) // true
Number.isFinite(Infinity) // false
Number.isFinite(NaN) // false

Number.isInteger(123) // true
Number.isInteger(9007199254740992) // true !!
Number.isInteger(12.3) // false
Number.isInteger(Infinity) // false
Number.isInteger(NaN) // false

Number.isSafeInteger(123) // true
Number.isSafeInteger(9007199254740992) // false
Number.isSafeInteger(12.3) // false
Number.isSafeInteger(Infinity) // false
Number.isSafeInteger(NaN) // false

// BigInts are not considered Integers:
Number.isInteger(1n) // false
Number.isSafeInteger(1n) // false
// But it is a number:
Number.isNaN(1n) // false
Enter fullscreen mode Exit fullscreen mode

Thirsty for more? Check out MDN Lexical grammar article.

Thank you for reading! Don't hesitate to share your suggestions and overall feedback in the comments.

Top comments (2)

drarig29 profile image
Corentin Girard • Edited

I think this is a mistake (at least, once you comment it returns true, and just after you say false):

Number.isSafeInteger(9007199254740992) // true !! 
Enter fullscreen mode Exit fullscreen mode

Also, you have a typo here:

Enter fullscreen mode Exit fullscreen mode
valeriavg profile image

Thank you, corrected.
The first one supposed to be Number.isInteger as it returns true for numbers above safe integer.