Solve JS numeric precision loss

Get into the habit of writing together! This is the 19th day of my participation in the "Nuggets Daily New Plan · April Update Challenge", click to view the details of the event .

Calculating the sum of two decimal numbers in JavaScript sometimes produces surprising results, I believe everyone knows this!

loss of precision

For example, the result we 0.1 + 0.1get in the calculation is 0.2, but 0.1 + 0.2the result of the calculation is not 0.3, but 0.30000000000000004

This phenomenon not only occurs in addition, but also in subtraction with similar results.

For example 1.2 - 1the result is 0.19999999999999996

This is not unique to JavaScript though, other programming languages ​​have the same problem.

For example output in the Python environment.

print(.1 + .2) 
复制代码

The result obtained is also: 0.30000000000000004

reason

The main reason for this problem is that computers store data as binary .

How to convert integer from decimal to binary

A decimal integer can be converted to binary by dividing it by 2. Take the quotient and keep dividing by 2 until it reaches zero.

Every time you perform this division, note the remainder . Now reverse the remainder list to get the number in binary form.

For example, I want to convert 29 to binary:

29÷2=14 excess1

14÷2=7 excess0

7÷2=3 excess1

3÷2=1 surplus1

1÷2=more than 01

The binary number representing decimal 29 is 11101.

E.g:

  • 1 is 1

  • 10 is 1010

Convert decimal from decimal to binary

Decimal decimals are converted into binary decimals using the "multiply 2 rounding, orderly arrangement" method. The specific method is: multiply the decimal fraction by 2 to obtain the product, take out the integer part of the product, then multiply the remaining fractional part by 2 to obtain a product, and then take out the integer part of the product, and so on, until the The fractional part is zero, and 0 or 1 is the last digit in binary. or until the required accuracy is achieved.

For example: I want to convert 0.375 to binary:

0.375*2=0.75 get 0

0.75*2=1.5 gets 1

0.5*2=1 gets 1, the decimal is gone, and the end. The final conversion to binary is 0.011

E.g:

  • 0.1 is 0.0001100110011001100110011001100110011001100110011001101
  • 0.2 is 0.001100110011001100110011001100110011001100110011001101

Not every decimal number can be represented perfectly in this binary format, as some numbers may be converted to

When JavaScript is calculating, it will first convert the decimal to binary and perform the calculation.

0.00011001100110011001100110011001100110011001100110011010 +
0.0011001100110011001100110011001100110011001100110011010 =
0.0100110011001100110011001100110011001100110011001100111
复制代码

The result obtained here is 0.0100110011001100110011001100110011001100110011001100111converted to decimal and is 0.300000000000000004

solution

third party library

Decimal

x = new Decimal(0.1)
y = x.plus(0.2) 
复制代码

bignumber

x = new BigNumber(0.1)
y = x.plus(0.2)    
复制代码

become an integer

The main idea is: first convert the decimal to split two strings, then calculate the length of the string of the fractional part, and then use this length to turn the decimal into an integer!

function add(num1, num2) {
  const num1Len = (num1.toString().split('.')[1] ).length;
  const num2Len = (num2.toString().split('.')[1] ).length;
  const maxLen = Math.pow(10, Math.max(num1Len, num2Len));
  return (num1 * maxLen + num2 * maxLen) / maxLen;
}
复制代码

toFixed

Guess you like

Origin juejin.im/post/7090940938184294407