Skip to main content

Building Blocks in JS

Datatypes in-depth - Numbers

JavaScript, the language that breathes life into your web pages, is known for its dynamic and flexible nature. But this flexibility can sometimes be a double-edged sword, especially when it comes to dealing with numbers. Whether you’re calculating the bill for a street-side chai break or managing transactions in a large-scale financial application, understanding how JavaScript handles numbers is crucial. In this article, we'll take a deep dive into the Number data type in JavaScript.

JavaScript categorizes numbers into two types:

  1. Regular Numbers: These are 64-bit floating-point numbers, following the IEEE-754 standard. They are the most common and versatile, capable of representing both integers and floating-point numbers.
  2. BigInt: Introduced in ECMAScript 2020, BigInt allows for the representation of integers of arbitrary length. This is especially useful when dealing with very large numbers that exceed the safe integer limit of regular numbers.

In this article, we’ll focus primarily on regular numbers and explore how JavaScript manages these in various scenarios.

Let's understand with an example, shall we? - Calculating a Large Transaction

Let’s say you’re running a small business in Bangalore, selling refurbished laptops. A customer orders 1,000 laptops, each priced at ₹50,000. Your task is to calculate the total bill.

let pricePerLaptop = 50000;
let quantity = 1000;
let totalBill = pricePerLaptop * quantity;

console.log(totalBill); // 50000000

Here, the total bill is ₹50,000,000. JavaScript handles this calculation with ease, as the result is within the range of what a regular number can represent.

Making Numbers More Readable

When dealing with large numbers like ₹50,000,000, it’s easy to lose track of the number of zeroes. JavaScript allows you to use underscores (_) to make such numbers more readable:

let totalBill = 50_000_000;
console.log(totalBill); // 50000000

This doesn’t affect the value of the number—it’s purely for readability.

Let's take another example:

Exponentiation

Another way to represent large numbers is through exponentiation. JavaScript lets you use the e notation to simplify things. For example, instead of writing 1 billion as 1000000000, you can write:

let billion = 1e9;
console.log(billion); // 1000000000

In our laptop business example, if the customer ordered 1 crore laptops (10 million), you could represent this as:

let quantity = 1e7;
let totalBill = pricePerLaptop * quantity;

console.log(totalBill); // 500000000000

Here, 1e7 represents 10 million, making the code cleaner and easier to understand.

Small Numbers and the e Notation

Just as e can represent large numbers, it can also represent very small numbers. Imagine you’re calculating the cost per millisecond for running a server that costs ₹3.6 per second. Since 1 second equals 1,000 milliseconds, the cost per millisecond would be:

let costPerSecond = 3.6;
let costPerMillisecond = costPerSecond / 1e3;

console.log(costPerMillisecond); // 0.0036

Essentially the e notation is very simple, you write a number, then write the character e, and then the exponential, i.e the number of zeros to multiply it by, got it?

so to write thousand you can simply write 1 followed by 3 zeros right?

so guess how to write it using the e notation.

Did you guess it right?

The right answer would be: 1e3

Hexadecimal, Binary, and Octal Numbers

JavaScript also supports hexadecimal, binary, and octal number systems, which can be useful in various scenarios, such as color representation, bitwise operations, or working with memory addresses.

For instance, if you’re assigning a color to your website’s background, you might use a hexadecimal color code:

let color = 0xFF5733; // Hexadecimal representation of the color
console.log(color); // 16734003 (decimal equivalent)

Or, if you’re working with low-level operations, you might use binary or octal numbers:

let binaryNumber = 0b1010; // Binary representation of 10
let octalNumber = 0o12; // Octal representation of 10

console.log(binaryNumber); // 10
console.log(octalNumber); // 10

Converting Numbers to Different Bases

Hexadecimal, Binary, and Octal Numbers

We have covered how javascript deals with number systems in the Number systems article in detail, but here let's get into some practical aspects of the same.

JavaScript also supports hexadecimal, binary, and octal number systems, which can be useful in various scenarios, such as color representation, bitwise operations, or working with memory addresses.

For instance, if you’re assigning a color to your website’s background, you might use a hexadecimal color code:

let color = 0xFF5733; // Hexadecimal representation of the color
console.log(color); // 16734003 (decimal equivalent)

Or, if you’re working with low-level operations, you might use binary or octal numbers:

let binaryNumber = 0b1010; // Binary representation of 10
let octalNumber = 0o12; // Octal representation of 10

console.log(binaryNumber); // 10
console.log(octalNumber); // 10

Converting Numbers to Different Bases

We have understood how to manually do this in the Number systems article, here let's leverage Javascript to do it for us, shall we?

JavaScript allows you to convert numbers to different bases using the toString method. This can be handy when you need to represent a number in a different numeral system:

let num = 255;
console.log(num.toString(16)); // "ff" (Hexadecimal)
console.log(num.toString(2));  // "11111111" (Binary)

In the context of our laptop business, if you wanted to create a short URL for an invoice ID, you could convert the ID to base 36:

let invoiceId = 123456;
console.log(invoiceId.toString(36)); // "2n9c"

Just an example to understand how we can leverage JS to simply things for us.

Rounding Numbers

Have you heard about floor and ceil? Imagine you are in a room, there is a floor and ceil, say the ceiling is number 1 and the floor is 0. Half the height of your room is how much?

Yes, 0.5 right?

Image it is a 10 foot tall room, so 5 foot would be 0.5, I hope you are able to imagine it.

Now, coming back to the topic of floor and ceil, floor will round up everything to the nearest number below. Say you are at 0.9, floor is o, but ceil does the opposite, for ceil, it is 1 - it rounds it up to 1.

Rounding numbers is a common operation in JavaScript, and the language provides several methods to do so:

  • Math.floor: Rounds down to the nearest integer.
  • Math.ceil: Rounds up to the nearest integer.
  • Math.round: Rounds to the nearest integer, with ties rounding up.
  • Math.trunc: Removes the fractional part without rounding.

It is simple, right?

Imagine you’re calculating the average rating for your business based on customer reviews. If the average rating comes out to be 4.7, you might want to round it up to the nearest whole number:

let averageRating = 4.7;
let roundedRating = Math.round(averageRating);

console.log(roundedRating); // 5

Or, if you want to always round down:

let roundedRating = Math.floor(averageRating);
console.log(roundedRating); // 4

Dealing with Precision

One of the quirks of JavaScript is that it sometimes struggles with precise calculations due to the way it handles floating-point numbers. A common example is adding 0.1 and 0.2:

console.log(0.1 + 0.2); // 0.30000000000000004

This might seem like a bug, but it’s actually a result of how numbers are stored in memory. JavaScript uses binary floating-point representation, which can’t precisely represent some decimal fractions.

To avoid issues like this, especially in financial calculations, you can round the result to a fixed number of decimal places:

let sum = 0.1 + 0.2;
console.log(sum.toFixed(2)); // "0.30"

This ensures that the result is displayed as 0.30 instead of 0.30000000000000004.

Handling Large Numbers with BigInt

If your laptop business expands and you start dealing with large financial transactions, you might encounter numbers that exceed the safe integer limit in JavaScript. This is where BigInt comes in handy.

let largeNumber = BigInt(12345678901234567890);
console.log(largeNumber); // 12345678901234567890n

With BigInt, you can safely handle numbers beyond the limits of regular numbers. However, keep in mind that BigInt and regular numbers are not directly interoperable, so you’ll need to convert between them when necessary.

Infinity and NaN

JavaScript also has special numeric values like Infinity and NaN (Not-a-Number). These are useful in cases where calculations exceed the range of representable numbers or when operations don’t yield a valid number.

For example, dividing by zero results in Infinity:

let result = 50 / 0;
console.log(result); // Infinity

On the other hand, operations that don’t produce a number result in NaN:

let result = "laptop" / 2;
console.log(result); // NaN

You can check for these values using isFinite and isNaN:

console.log(isFinite(result)); // false
console.log(isNaN(result)); // true

Object.is for Strict Comparisons

JavaScript also provides Object.is for strict comparisons, which is particularly useful when dealing with edge cases like NaN and -0.

console.log(Object.is(NaN, NaN)); // true
console.log(Object.is(0, -0)); // false

Numbers in JavaScript may seem simple at first glance, but as we’ve seen, they have many intricacies that can catch you off guard. Whether you’re calculating bills for a large order of refurbished laptops, managing financial transactions, or working with different numeral systems, understanding how JavaScript handles numbers is crucial.

With that let's move to the next Data structure, Strings!