Decimal and binary conversion

Decimal integer to binary method: mod 2; Decimal Conversion from decimal to binary: Multiply by 2 and divide

Decimal 0.1 to binary, multiplied by two the whole process:

0.1 * 2 = 0.2 to 0.2 * 2 = 0.4 # 0 # 0 # 0 0.8 * 0.4 * 2 = 0.8 2 = 1.6 # 1 0.6 * 2 = 1.2 to 0.2 * 2 = 0.4 # 0 # 1...Copy the code

This is a binary infinite repeating decimal, but computer memory is limited, we can’t store all the decimal places. So what’s the trade-off between precision and memory?

The answer is: at some point of accuracy, it is discarded. The trade-off, of course, is that inside the computer, 0.1 is not an exact 0.1 at all, but a 0.1 with a rounding error. By the time the code is compiled or interpreted, 0.1 has been rounded to an internal computer number so close that a small rounding error has occurred before the calculation has even begun. This is why 0.1 + 0.2 does not equal 0.3.

Of course, the result of the calculation of two numbers with errors is very likely to be different from what we expect. Notice the word “probably” in the previous sentence? Why is it likely?

Why is 0.1 + 0.1 equal to 0.2

The answer is that two values with rounding errors cancel each other out when they sum, but this “negatives make positives cancel each other out” is not necessarily reliable, and the rounding errors may not cancel out when the two numbers are floating point numbers with digits of different lengths.

For example, for 0.1 + 0.3, the result is not really 0.4, but 0.4 is the closest to the true result, closer than any other floating point number. Many languages simply display the result as 0.4, rather than the actual result of a floating point number.

Also note that binary can accurately represent decimals with a finite number of digits and a multiple of 2 in the denominator, such as 0.5, which has no rounding error inside the computer. So 0.5 + 0.5 === 1

Can a computer meet all its computing needs with this random rounding

Let’s look at two realistic scenarios:

  • To an engineer building a railway, it makes no difference whether it is 10 meters wide or 10.0001 meters wide. Railroad engineers do not need such precision as 0. X
  • For a chip designer, 0.0001 meter would be a huge difference, and he would never have to deal with more than 0.1 meter

In different industries, the accuracy required is not linear, and we allow (inconsequential to the result) errors. Both 10.0001 and 10.001 are acceptable in the opinion of the railway engineer.

Errors are allowed, but problems can arise if the programmer is not careful when using floating-point numbers for calculations or logical processing. Remember, never directly compare the sizes of two floating points:

Var a = 0.1 var b = 0.2 if (a + b === 0.3) {// doSomething}Copy the code

How to enter floating point arithmetic in JS

Convert floating point operations to integer calculations

Integers are perfectly accurate and have no rounding error. For example, some calculations about RMB are divided into basic units, calculated by minutes, displayed and then converted into yuan. Of course, there are some problems with this, which will bring extra workload. If a new currency unit is added to the RMB on that day, the system’s scalability will also be tested.

usebignumberThe computations

Bignumber.js will make the floating-point calculation as accurate as we want it to be.

{let x = new BigNumber(0.1); Let y = new BigNumber(0.2) let z = new BigNumber(0.3) console.log(z.edals (x. dd(y))) // 0.3 === 0.1 + 0.2, true console.log(z.minus(x).equals(y)) // true console.log(z.minus(y).equals(x)) // true }Copy the code
{let x = 0.2 console.log(x * x === 0.04) // false let y = new BigNumber(0.2) let r = y.mul(y) // 0.04 Console. log(r.quals (new BigNumber(0.04))) // true}Copy the code

For more examples, see the official bignumber.js example.

summary

This paper mainly introduces floating point calculation problems, simple answer why and how to do two questions:

  • Why 0.1 + 0.2 does not equal 0.3. Because computers can’t accurately represent floating point numbers like 0.1 and 0.2, calculations are made using numbers with rounding errors
  • Not all floating point numbers have a rounding error inside the computer; 0.5, for example, has no rounding error
  • An operational knot with a rounding error might be what we want it to be because “two negatives make a positive”
  • How to do? One way is to use integers instead of floating-point numbers. Instead of directly comparing two floating-point numbers, use a library like bignumber.js

2. The three party libraries

This is a more comprehensive approach, and I recommend two libraries that I contact with at ordinary times

1).Math.js

An extensive math library specifically for JavaScript and Node.js. Support for numbers, large numbers (numbers beyond safe numbers), complex numbers, fractions, units and matrices. Powerful and easy to use.

2).big.js