Numbers and BigInt in JavaScript

How to create a number

As we've discussed before, JavaScript allows you to create integers and fractional numbers like this:

javascript
1100; // integer
212.09; // factional number

Or, you can use the scientific notation:

javascript
13.14e5; // -> 314000
23.14e-5; // -> 0.0000314

JavaScript also allows you to create numbers in binary, hex, or octal format.

javascript
1let dec = 255;
2let bin = 0b11111111; // The prefix 0b creates a binary number
3let oct = 0o377; // The prefix 0o creates a octal number
4let hex = 0xff; // The prefix 0x creates a hexadecimal number
5
6console.log(dec == oct);
text
1true

These are four different ways you can create the number 255 in JavaScript, and when equate the different formats, JavaScript will tell you they are the same.

Number encoding

No matter what format you use, after compilation, these numbers will be converted into their binary format, which is a series of 1s and 0s that can be processed by computers. For example, the decimal number 5 will be converted into binary number 101.

That being said, please note that this course does not go into the details of number encoding in JavaScript. For now, you only need to understand that JavaScript numbers are encoded based on the 64-bit double-precision floating-point format, which is represented just like the scientific notation we are all too familiar with, except in binary form.

With that 64 bits, JavaScript uses 52 bits to represent the fraction, a number between 1 and 0. It then uses 11 bits for the exponent and 1 bit for the sign, either positive (1) or negative (0).

numbers encoding in JavaScript

This method of number encoding does lead to some problems.

For example, in JavaScript, operations involving fractional numbers are often inaccurate. For instance, we all know 0.1 plus 0.2 equals 0.3, but when you perform that calculation using JavaScript, it gives 0.30000000000000004.

0.1 + 0.2 in JavaScript

This is due to how fractional numbers are encoded.

fraction number encoding

So, the binary number 0.101 represents the decimal number 0.625.

We will not bore you with too many mathematical details here. You only need to know that most fractional numbers, when converted into binary form, will have an infinite number of digits. And since JavaScript uses limited bits to represent a number, it will have to be rounded. That's what is causing the inaccuracies.

In practice, this is not going to be too much of a problem because most tasks don't require extremely high precision. But you should treat fractional numbers as approximates, not precise numbers.

However, if you do run into such situations where the inaccuracy of fractional calculations are causing problems, you should consider multiplying the numbers to convert them into integers, and then divide.

javascript
1(0.1 * 10 + 0.2 * 10) / 10;
text
10.3

What is a BigInt

On the other hand, when working with integers, JavaScript is guaranteed to be accurate as long as you are working within its maximum range, which is about nine quadrillion. However, once you exceed JavaScript's capabilities, the numbers will not be represented precisely.

exceed maximum integer

Although unlikely, but if you really need to work with integers larger than nine quadrillion, append the letter n to the end of the integer.

javascript
199999999999999999n;

bigint

This is called a BigInt in JavaScript. A data type similar to numbers, but it allows you to work with integers larger than nine quadrillion.

However, it is important to note that BigInt can only encode integers, not fractional numbers.

no fraction in bigint

And the arithmetic operations between a number and a BigInt are forbidden.

number plus bigint

Arithmetic operations

You can perform arithmetic operations with numbers using JavaScript.

javascript
13 + 5 * 2;

As you would have expected, multiplication and division happen before addition and subtraction. You can change the order of calculation using parentheses.

javascript
1(3 + 5) * 2;

arithmetic operations

Of course, there is also exponential, which is denoted by **.

javascript
12 ** 3; // -> 8
25 ** 2; // -> 25

Any number raised to the exponent of 0 equals 1.

javascript
12 ** 0; // -> 1
25 ** 0; // -> 1

Everything works exactly the same as what you studied in school. However, there is one operation you might not recognize, which is the modulo (%) operation. It calculates the remainder after dividing two numbers. For example:

javascript
125 % 5; // -> 0
2
325 % 10; // -> 5
4
525 % 15; // -> 10

In this case, 25 divided by 5 equals 5, with no remainder, so 25 % 5 equals 0. On the other hand, 25 divided by 10 equals 2, with 5 remaining, so 25 % 10 equals 5.

Special numbers

Besides the integers and fractional numbers, there are also two special numbers in JavaScript. The first one we must cover is NaN, which stands for "Not a Number". It has some very interesting characteristics, both as a programming concept and a mathematical concept.

First of all, "Not a Number" is a number. Strange, right? But you can verify this claim using the typeof operator.

javascript
1typeof NaN;
text
1number

NaN is a number

NaN is used when an arithmetic operation that should give a number returns something that is not a number, or something that doesn't make sense. For instance, let's try to perform an arithmetic calculation on undefined, and it should give NaN.

javascript
1console.log(undefined + undefined);
text
1NaN

sum of undefined

NaN is also the only value in JavaScript that does not equal itself.

javascript
1NaN == NaN; // -> false

NaN does not equal NaN

Infinity is another special numeric value in JavaScript. It behaves just like the mathematical definition of the infinity (∞), except when the arithmetic operation generates a value that exceeds JavaScript's capabilities, the operation will also give Infinity.

javascript
110 ** 1000;

infinity

Mathematically, this should give you a number, but as we've discussed before, JavaScript can only represent 2^64 numbers, and this result exceeds that range.

Comparisons

Besides the arithmetic calculations, you can also perform comparison operations on numbers. Commonly used operators include:

  • >: greater than
  • <: less than
  • >=: greater than or equal to
  • <=: less than or equal to
  • ==: equal
  • !=: not equal

The result of a comparison would be a Boolean value, either true or false.

javascript
1console.log(1 > 2);
2console.log(1 < 2);
3console.log(1 >= 1);
4console.log(1 <= 2);
5console.log(1 == 1);
6console.log(1 != 1);
text
1false
2true
3true
4true
5true
6false

Number methods

Number methods are helper functions associated with the number type. They allow you to manipulate the numeric data without altering the original value. Here are some of the most commonly used examples:

  • toString()

The toString() method is used to convert a number into a string.

javascript
1let x = 123;
2
3console.log(x.toString());
4console.log(typeof x.toString());
text
1123
2string
  • toExponential()

toExponential() returns a string, representing the number in scientific notation.

javascript
1let x = 123;
2
3console.log(x.toExponential());
4console.log(typeof x.toExponential());
text
11.23e+2
2string
  • toFixed()

toFixed() returns a string representing the number rounded to the specified number of decimals.

javascript
1let x = 123.12345;
2
3console.log(x.toFixed(0));
4console.log(x.toFixed(2));
5console.log(x.toFixed(4));
6console.log(x.toFixed(6));
7
8console.log(typeof x.toFixed(2));
text
1123
2123.12
3123.1235
4123.123450
5string
  • toPrecision()

toPrecision() returns a string representing the number rounded to the specified number of digits.

javascript
1let x = 123.12345;
2
3console.log(x.toPrecision(2));
4console.log(x.toPrecision(4));
5console.log(x.toPrecision(6));
6
7console.log(typeof x.toPrecision(2));
text
11.2e+2
2123.1
3123.123
4string