Fun with JavaScript Numbers

Share this article

Key Takeaways

  • All numbers in JavaScript are represented using the Number data type, which includes integers, real numbers, hexadecimal numbers, and numbers written in scientific notation. However, JavaScript internally represents all numbers as IEEE 754 floating point data, meaning JavaScript math is not 100% accurate.
  • JavaScript defines a number named Not-a-Number (NaN), which is used to represent non-numbers as numbers. NaN is the only value in JavaScript that does not equal itself, and can be tested using the isNaN() function.
  • JavaScript has quirks such as the signed zero, resulting in a positive zero (+0) and a negative zero (-0), which are considered distinct values but are indistinguishable by JavaScript’s comparison operators. Division by zero in JavaScript yields Infinity, while division by negative zero yields -Infinity.
Data types are an essential component of every programming language, and numbers are perhaps the most important of all data types. After all, computers are really just expensive calculators. Like any worthwhile programming language, JavaScript supports numerical data. However, like many other aspects of JavaScript, numbers have several intricacies which can bite you if you’re not careful. This article explores numerical data and some of its quirks. Note: before reading this article, you should have a basic familiarity with JavaScript data types.

The Number Type

In JavaScript, all numbers are represented using the Number data type. This includes integers, real numbers, hexadecimal numbers, and numbers written in scientific notation. The following example verifies this by applying the typeof operator to a variety of numbers. Each application of typeof in this example returns number.
typeof(100);
typeof(3.14);
typeof(0xDEADBEEF);
typeof(7.89e2);
In the previous example, the numbers took on a variety of formats. However, internally, all JavaScript numbers are actually represented as IEEE 754 floating point data. This is important because it means that JavaScript has no concept of integers, despite the language’s parseInt() function. It also means that JavaScript math is not 100% accurate. For example, consider the following expression.
(0.1 + 0.2) === 0.3
If you are unfamiliar with floating point numbers, you would certainly expect this expression to evaluate to true. After all, 0.1 + 0.2 does equal 0.3. However, due to the way floating point numbers work, the sum is actually 0.30000000000000004. The difference is slight, but it is enough to cause the entire expression to evaluate as false.

Positive and Negative Zero

Another quirk of the IEEE 754 standard is the signed zero. This results in two zeroes – a positive zero, +0, and a negative zero, -0. This may seem strange, but the fun is just beginning. Clearly, these are two distinct values, otherwise there would only be a single zero. However, if you display either of the zeroes, the sign is dropped. For example, the following code attempts to display the two zero values, side-by-side.
alert((+0) + " " + (-0));
// displays 0 0
To make matters worse, JavaScript’s comparison operators can’t seem to tell the two values apart either, as shown in the following example.
alert((+0 === -0));
// displays true
alert((-0 < +0));
// displays false
There is a fairly simple workaround for this problem. In JavaScript, division by zero yields Infinity. Similarly, division by negative zero yields -Infinity
. Therefore, to determine if a number is equal to -0, we must check that it is a zero, then perform division with it as the denominator, and check for -Infinity as shown below.
function isNegativeZero(x) {
  return (x === 0 && (1/x) === -Infinity);
}

Not-a-Number

JavaScript actually defines a number named Not-a-Number, or NaN. NaN is a falsy value that is used to represent non-numbers as numbers. This value is interesting because its very name precludes it from being a number, yet typeof(NaN) is number. NaN is also fun because it is the only value in JavaScript that does not equal itself. For example, the following code will return false.
alert((NaN === NaN));
// displays false
Instead of using the comparison operators, you can test for NaN using the isNaN() function, as shown below.
isNaN(1);
// returns false
isNaN(NaN);
// returns true
However, isNaN() is also fun because it can be misleading. If you pass in a value that can be coerced to a number, isNaN() will return false. In the following example, isNaN() is called with several values that are clearly not numbers. However, each call returns false.
isNaN(true);
isNaN(false);
isNaN("");
isNaN(null);
// all return false
A better way to check for NaN is by exploiting the fact that it is not equal to itself. The following function tests for NaN using strict inequality. This function will only return true for the value NaN.
function isNotANumber(x) {
  return x !== x;
}

Other Fun Times

There are a few other scenarios which can lead to problems with numbers. For starters, you should beware of old browsers that allow global properties like Infinity, NaN, and undefined to be redefined to new values. For example, the following code could create a lot of problems if NaN is used frequently. Luckily, modern browsers will ignore assignments to the previously mentioned properties. Strict mode goes one step further by turning these silent failures into errors.
NaN = 1;
...
isNaN(NaN);
// now returns false
Another fun to diagnose error comes from adding a number and a string. An example of this is shown below. In this case, string concatenation overrides addition. This causes foo to be converted to the string "100". The final result is the string "1001", which is much different from the expected value of 101. This type of error is more common than you think, and tends to occur when reading user input.
var foo = 100;
var bar = "1";

alert(foo + bar);
// displays "1001"

Conclusion

This article has explored some of the idiosyncrasies of numbers in JavaScript. Hopefully, you now understand why these issues arise, and how you can avoid them. And, although you may not run into cases like the negative zero very often, at least now you are prepared.

Frequently Asked Questions (FAQs) about JavaScript Numbers

What happens when you divide a number by zero in JavaScript?

In JavaScript, when you divide a number by zero, the result is Infinity. This is because any number divided by zero is mathematically undefined, but JavaScript represents it as Infinity for practical purposes. However, if you divide zero by zero, the result is NaN (Not a Number) because this operation is indeterminate in mathematics.

How does JavaScript handle BigInt division by zero?

BigInt is a built-in object in JavaScript that provides a way to represent whole numbers larger than 2^53-1, which is the largest number JavaScript can reliably represent with the Number primitive. If you try to divide a BigInt by zero, JavaScript throws a RangeError, indicating that the operation is not valid.

How can I prevent or handle divide by zero errors in JavaScript?

You can prevent or handle divide by zero errors in JavaScript by using conditional statements to check if the denominator is zero before performing the division operation. If the denominator is zero, you can then decide how to handle it, for example, by returning a specific value or displaying an error message.

Why is 0 divided by 0 in JavaScript NaN?

In mathematics, the expression 0/0 is undefined because it does not have a clear, definite value. In JavaScript, undefined mathematical operations result in NaN (Not a Number). So, when you divide zero by zero in JavaScript, the result is NaN.

What is the difference between NaN and Infinity in JavaScript?

In JavaScript, NaN (Not a Number) and Infinity are special numeric values. NaN represents a value that is not a legal number, often resulting from undefined or indeterminate mathematical operations. On the other hand, Infinity represents a number that is larger than any possible number, often resulting from dividing a number by zero.

How can I check if a result is NaN in JavaScript?

You can use the isNaN() function in JavaScript to check if a result is NaN. This function returns true if the argument is NaN, and false otherwise.

How can I check if a result is Infinity in JavaScript?

You can use the isFinite() function in JavaScript to check if a result is a finite number. This function returns false if the argument is positive or negative Infinity, and true otherwise.

What is the significance of the Number primitive in JavaScript?

The Number primitive in JavaScript is used to represent numeric values. It can represent integer values as well as floating-point numbers. However, it can only reliably represent numbers up to 2^53-1.

How can I handle large numbers in JavaScript?

For handling large numbers beyond the safe integer limit in JavaScript, you can use the BigInt object. BigInt allows you to represent whole numbers larger than 2^53-1.

What is a RangeError in JavaScript?

A RangeError is thrown in JavaScript when a value is not within the expected range. For example, trying to divide a BigInt by zero results in a RangeError.

Colin IhrigColin Ihrig
View Author

Colin Ihrig is a software engineer working primarily with Node.js. Colin is the author of Pro Node.js for Developers, and co-author of Full Stack JavaScript Development with MEAN. Colin is a member of the Node.js Technical Steering Committee, and a hapi core team member. Colin received his Bachelor of Science in Engineering, and Master of Science in Computer Engineering from the University of Pittsburgh in 2005 and 2008, respectively.

Raw JavaScript
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week