Skip to content

Commit a5d8784

Browse files
committed
learn about Floating Point Imprecision in JS
1 parent 4601d11 commit a5d8784

File tree

1 file changed

+49
-0
lines changed

1 file changed

+49
-0
lines changed

More-on-Numbers-and-Strings/README.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
| Contents |
44
| :--- |
55
| [How `Numbers` Work and Behave in JS](#how-numbers-work-and-behave-in-js) |
6+
| [Floating Point (Im)Precision](#floating-point-imprecision) |
67

78
## How [`Numbers`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number) Work and Behave in JS
89

@@ -37,3 +38,51 @@ console.log(Number.MAX_VALUE); // 1.7976931348623157e+308
3738
It's worth noting that when performing operations that exceed the representable range or precision, JavaScript doesn't throw an error. Instead, it provides an imprecise result. For example, if you subtract an integer from the smallest representable number, the result may be imprecise due to exceeding the bit range available for numbers. JavaScript will truncate the bits and convert the result back to a decimal number, which may lead to unexpected outcomes. The conversion between the binary system (used internally by JavaScript) and the decimal system (used for output) can be perplexing, but understanding the limitations and potential inaccuracies is essential.
3839

3940
While working with such large numbers or numbers with numerous decimal places is infrequent in everyday programming, it's crucial to be aware of these limitations to avoid unexpected behaviors.
41+
42+
## Floating Point (Im)Precision
43+
44+
In JavaScript, floating-point imprecision refers to the inherent limitations of representing real numbers with floating-point numbers. JavaScript uses the IEEE 754 standard to represent floating-point numbers, which uses a fixed number of bits to represent a decimal number. While this representation is very efficient and suitable for most cases, it comes with some limitations.
45+
46+
One significant limitation is that certain decimal numbers cannot be precisely represented in binary format. As a result, when performing arithmetic operations or comparisons with floating-point numbers in JavaScript, you may encounter unexpected imprecisions, especially when dealing with decimal numbers that have repeating fractions or cannot be represented exactly in binary.
47+
48+
So, in simple terms, floating-point imprecision in JavaScript is a result of the fundamental differences between the binary system used internally by JavaScript and the decimal system in which programmers work. When performing calculations involving decimal numbers with fractions (e.g., 0.1, 0.2, 0.4), the binary representation may lead to slight inaccuracies due to the limitations of representing certain decimal numbers in binary format.
49+
50+
The issue arises because certain fractions, which have repeating fractions in the decimal system, cannot be precisely represented in the binary system. For example, 0.2 in the decimal system is equivalent to 1/5, and 0.4 is equivalent to 2/5. In the binary system, there are certain fractions, like 1/5, for which there is no finite representation (just as there is no perfect representation for 1/3 in the decimal system).
51+
52+
When JavaScript converts these decimal numbers to the binary system for calculations, it may lead to imprecise results. For example, when adding 0.2 and 0.4, the expected result would be 0.6, but due to the binary representation, JavaScript gives a slightly imprecise result (e.g., 0.6000000000000001). As a result, direct equality comparisons between floating-point numbers can lead to unexpected outcomes:
53+
54+
```javascript
55+
console.log(0.2 + 0.4 === 0.6); // Output: false
56+
```
57+
58+
To mitigate this issue, developers can use techniques like using an epsilon value for approximate comparisons. It is recommended to avoid direct equality comparisons between floating-point numbers. Instead, you can use a small tolerance or epsilon value to check if two numbers are approximately equal
59+
60+
```javascript
61+
function areAlmostEqual(num1, num2, epsilon = 0.0001) {
62+
return Math.abs(num1 - num2) < epsilon;
63+
}
64+
65+
console.log(areAlmostEqual(0.1 + 0.2, 0.3)); // Output: true
66+
67+
```
68+
69+
Or rounding methods like [`toFixed`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed) to control the number of decimal places displayed to the user.
70+
71+
```javascript
72+
// Demonstrating Imprecision
73+
console.log(0.2.toFixed(20))
74+
// Output - '0.20000000000000001110'
75+
76+
console.log(0.2.toFixed(2))
77+
// Output - '0.20'
78+
```
79+
80+
Alternatively, when absolute precision is required, developers may work with integers by multiplying decimal numbers by a fixed factor (e.g., multiplying by 100 to work with cents) to avoid floating-point imprecision.
81+
82+
Readings:
83+
84+
- [Floating-point arithmetic](https://en.wikipedia.org/wiki/Floating-point_arithmetic)
85+
86+
- [2ality – JavaScript and more](https://2ality.com/2012/04/number-encoding.html)
87+
88+
- [Dealing with float precision in Javascript](https://stackoverflow.com/questions/11695618/dealing-with-float-precision-in-javascript)

0 commit comments

Comments
 (0)