Problem description

I believe that a lot of JavaScript contact children’s shoes, have encountered such a problem, even I have encountered this problem in the interview, just ask, 0.1 + 0.2 =? I was so close to getting it.

I’m sure you all know this result, but why? Is it only 0.1 + 0.2 that has this strange phenomenon? Or does that only happen with addition? Can other operations do the same thing? Today I want to talk to you about why this happens.

Obviously, this phenomenon is not unique to addition. For example:

As you all know, when we enter a value, computers don’t store it directly. You’ve probably heard that computers store decimal numbers in a long binary string of zeros and ones. A bunch of zeros and ones? So how big is this bunch?

Cause analysis,

You may or may not have heard of IEEE754, the floating-point standard. IEEE754 is divided into single precision, double precision (64-bit), extended single precision, extended double precision. JavaScript uses double precision (64 bits) to handle floating point numbers. A quick look at what a double is (64 bits) :

  • 64-bit double: A number is stored with fixed 64-bit zeros and ones;

  • The computer divides the 64 bits into three parts:

  • Sign bit: only 0 and 1, used to distinguish positive and negative numbers. 0: positive, 1: negative

  • Exponent bit: The exponent in which a number is stored, such as 2^4, which is 4. 11

  • Significant bit: The base to store a number, such as 1.11 ^ 4, which is 1.11. 52

I was thinking, all of these integers can be stored in the computer completely, then 0.1 naturally is no problem, and 0.1 is not an irrational number or an infinite repeating decimal. If that’s what you’re thinking, you’ve got an idea. You only have 64 digits, but what about infinite repeating decimals and irrational numbers?

If you know the binary conversion method, you can do the calculation (here is not to do the calculation process of the demonstration, it doesn’t matter if you don’t know).

0.1 in binary: 0.00 0110 0110… 0110 infinite loop 0110. And 0.2 is an infinite loop. But using IEEE754, you can’t store this infinite number, because IEEE754 only has 52 significant bits. This forces the computer to take an approximate number. So there is the problem of loss of accuracy.

The solution

NPM install –save Decimal.js

Github address: github.com/MikeMcl/dec…

Usage:

  • Add:new Decimal(a).add(new Decimal(b)).toNumber())
  • Subtraction: new Decimal(a).sub(new Decimal(b)).tonumber ()
  • Multiplication: new Decimal(a).mul(new Decimal(b)).tonumber ())
  • Division: new Decimal(a).div(new Decimal(b)).tonumber ())

More calculation methods can be found in the official documentation.

Our company asked our department to develop a small program to calculate year-end bonus and individual income tax, and there would be a lot of such data processing. I got up and fell in this hole. If you have a better solution, let me know in the comments. Thank you in this first!

Matters needing attention

A little bit of information about numbers, NaN is not equal to any number. Such as NaN! == 0 returns true. In addition to this, you may also think of the following questions

(0.2) > (0.3-0.1)Copy the code

From a code point of view, this is perfectly fine, but you might wonder how I could possibly write this code. Maybe the problem would become a lot more obvious if I switched to the following

Let a = 0.1, b = 0.2, c = 0.3 if (a > (c - b)) {... do something }Copy the code