1.1 Rounding Floating-Point Numbers
Floating-point numbers are called floating point number in English — numbers with a floating point: in the US, a dot is used to separate the integer part from the fractional part. That’s where the name float comes from.
As we’ve discussed before, when converting a floating-point number (float) to an integer (int), it always rounds down to the nearest whole number — the fractional part is simply dropped. But hey, it’s easy to imagine a situation where you need to round a floating-point number to the nearest integer or even up. What do you do?
For such a case in JavaScript, there’s a built-in function called round(). It was created before the Math library, so it isn’t part of it. However, functions for rounding down and rounding up are in the Math library.
The Math.round() Function
The Math.round() function rounds a number to the nearest integer:
Math.round(floating_point_number)
This function returns the integer closest to the input floating-point number.
Examples:
| Command | Result |
|---|---|
let x = Math.round(4.1); |
4 |
let x = Math.round(4.5); |
5 |
let x = Math.round(4.9); |
5 |
The Math.ceil() Function
The Math.ceil() function rounds a number up to the next integer:
| Command | Result |
|---|---|
let x = Math.ceil(4.1); |
5 |
let x = Math.ceil(4.5); |
5 |
let x = Math.ceil(4.9); |
5 |
The Math.floor() Function
The Math.floor() function rounds a number down to the nearest integer:
| Command | Result |
|---|---|
let x = Math.floor(4.1); |
4 |
let x = Math.floor(4.5); |
4 |
let x = Math.floor(4.9); |
4 |
If you have trouble remembering these commands, here’s a little English tip:
- math — mathematics
- round — circle/round
- ceiling — ceiling
- floor — floor
1.2 How Floating-Point Numbers Work
The number type in JavaScript can store values ranging from -1.7*10308 to +1.7*10308. This huge range of values is due to the fact that the number type is structured differently compared to integer types. Each number variable contains two numbers: the first is called the mantissa, and the second is the exponent.
For instance, let’s say we’ve got the number 123456789, and we’ve stored it in a number type variable. The number will then be converted into 1.23456789*108, and inside the number type, it will store 1.23456789 and 8. The red part highlights the "significant part of the number" (mantissa), and the blue part is the exponent.
This approach allows for storing both very large and very small numbers. However, since the number is limited to 8 bytes (64 bits), and part of these bits are used for storing the exponent (as well as the sign of the number and the sign of the exponent), the maximum length of the mantissa is limited to 15 digits.
This is a very simplified description of how floating-point numbers work. For a more detailed explanation, check out this link.
1.3 Precision Loss When Working with Floating-Point Numbers
When working with floating-point numbers, always remember that they are not exact. There will always be rounding errors, conversion errors when switching from decimal to binary, and, most commonly, precision loss when adding/subtracting numbers of very different magnitudes.
This last bit can be especially unexpected for programming beginners.
If you subtract 109 by 1/109, you’ll end up with 109 again.
| Subtracting Numbers of Very Different Magnitudes | Explanation |
|---|---|
| 1000000000.000000000 - 0.000000001 1000000000.000000000 |
The second number is far too small, so its significant part is ignored (marked in gray). The red highlights the 15 significant digits. |
What can I say — programming isn’t math.
1.4 The Danger of Comparing Floating-Point Numbers
Another tricky situation arises when comparing floating-point numbers. Since rounding errors can occur when working with these numbers, you could run into cases where floating-point numbers should be equal but aren’t. Or the opposite: numbers that shouldn’t be equal but are.
Example:
| Command | Explanation |
|---|---|
let a = 1000000000.0let b = 0.000000001let c = a – b |
The variable a will have the value 1000000000.0.The variable c will also have the value 1000000000.0(the number in variable b is just too small). |
In the above example, a and c shouldn’t be equal, but they are.
Here’s another example:
| Command | Explanation |
|---|---|
let a = 1.00000000000000001let b = 1.00000000000000002 |
The variable a will have the value 1.0.The variable b will also have the value 1.0. |
In practice, floating-point numbers are compared like this:
If the difference (absolute value) between the two numbers is smaller than some very small value, they are considered equal.
Example:
let a = 0.00000000012;
let b = 0.000000000011;
if (Math.abs(a - b) < 0.00001) {
console.log("equal");
} else {
console.log("not equal");
}
GO TO FULL VERSION