When learning JavaScript, you are warned that 0.1 + 0.2 != 0.3. The result is equal to 0.30000000000004.

This's not a JavaScript error; it's your processor doing this.

0.1 + 0.2 == 0.3 -> false

0.1 + 0.2 -> 0.30000000000000004

Why do these inaccuracies happen?

In base 10, which is the common base we use in everyday life, we can represent a number like 0.1 as a finite number - meaning it can be expressed as one decimal digit. However, if we try to write this in binary, we get something strange.

For 0.1 in the standard binary64 format, the representation can be written exactly as

  • 0.0001100110011001100110011001100110011001100110011001101 in binary
  • 0.1000000000000000055511151231257827021181583404541015625 in decimal

In particular, 0.1 + 0.2 is really

0.1000000000000000055511151231257827021181583404541015625 + 0.200000000000000011102230246251565404236316680908203125 = 0.3000000000000000444089209850062616169452667236328125

What is Floating Point in JavaScript

In Javascript, all numbers are encoded as double precision floating point numbers, following the international IEEE 754 standard.

IEEE 754 double-precision number uses 64 bits to represent 3 parts:

  • 1 bit for the sign (positive or negative)
  • 11 bits for the exponent (-1022 to 1023)
  • 52 bits for the mantissa (representing a number between 0 and 1)

     

Floating-point numbers are represented as binary (base 2) fractions. Regrettably, most decimal fractions cannot be represented exactly as binary fractions. The decimal floating-point numbers you enter are only approximated by the binary floating-point numbers stored in the machine. That being said, you'll see that floating-point arithmetic is not 100% accurate.

Managing representational errors

  • If you are displaying number content to a user, performing sensitive calculations for orders, purchasing, logistics, or similar, then built-in methods such as toPrecisionand, Math.x are generally sufficient. The situation will let you know the significance of the numbers you’re dealing with.

function numAdd(num1, num2) {
   var baseNum, baseNum1, baseNumb2;
   try {
   baseNum1 = num1.toString().split(".")[1].length;
   } catch (e) {
   baseNum1 = 0;
   }
   try {
   baseNum2 = num2.toString().split(".")[1].length;
   } catch (e) {
   baseNum2 = 0;
   }
   baseNum = Math.pow(10, Math.max(baseNum1, baseNum2));
   return (Math.round(num1*baseNum1) + Math.round(num2*baseNum2)) / baseNum;
}

numAdd(0.1, 0.2) => 0.3

  • You can easily break up numbers in JavaScript via strings since JavaScript strings are Array-like. toString, toFixed, and isInteger are also useful number and prototype methods.

var total = 0.1 + 0.2;

total.toFixed(1); => 0.3

  • If native precision lacks significance, various libraries can deliver more accuracy within all programming languages, but they should be avoided unless necessary (e.g., a calculator app requires precision).

Conclusion

Most decimals have infinite representations in binary. Due to the limitation of memory, rounding errors may be introduced in numbers whose binary equivalent does not fit even the Double Precision Format. So it's very important to tackle the Floating Point errors in JavaScript issues sooner rather than later. Ideally, before you start writing the first line of code for your application.

 

References:

https://en.wikipedia.org/wiki/Double-precision_floating-point_format

https://en.wikipedia.org/wiki/IEEE_754

https://www.w3schools.com/js/js_numbers.asp

External image links:

https://commons.wikimedia.org/wiki/File:IEEE_754_Double_Floating_Point_Format.svg

https://www.bing.com/

 

Leave a comment

*