Home  >  Article  >  Web Front-end  >  Some little knowledge about calculation accuracy in javascript (summary)

Some little knowledge about calculation accuracy in javascript (summary)

青灯夜游
青灯夜游Original
2018-09-17 15:07:042524browse

This chapter will introduce you to some small knowledge about calculation accuracy in JavaScript (summary), so that you can understand how binary is converted between decimals, how JavaScript saves numbers, how JavaScript reads numbers, and finally explains with examples. How does javascript solve calculation errors caused by accuracy issues. It has certain reference value. Friends in need can refer to it. I hope it will be helpful to you.

1. Prerequisite knowledge points

1. How to convert decimal to binary?

Divide the integer part by two and take the remainder until the quotient is 0. Arrange in reverse order. Multiply the decimal part by 2 and round up. Arrange in order until the decimal part of the product is 0 or the required accuracy is reached.

8转为二进制是多少?

8 / 2 = 4...0  取0
4 / 2 = 2...0  取0
2 / 2 = 1...0  取0
1 / 2 = 0...1  取1

二进制结果为:1000

0.25转为二进制是多少?

0.25 * 2 = 0.50  取0
0.50 * 2 = 1.00  取1

二进制结果为:01

于是可得出8.25的二进制表示:1000.01

2. How to convert binary to decimal?

Note: The conversion from binary to decimal does not separate the integer part and the decimal part.

二进制1000.01转为十进制

1 * 2^3 + 0 * 2^2 + 0 * 2^1 + 0 * 2^0 + 0 * 2^-1 + 0 * 2^-2 = 8.25

2. How does javascript save numbers?

The numbers in JavaScript are 64-bit double-precision floating point numbers that use the IEEE 754 standard.

  • sign bit (sign): used to represent the positive and negative sign, 1 bit (0 means positive, 1 means negative)

  • exponent( Exponent): used to represent the power, 11 digits

  • mantissa (mantissa): used to represent the accuracy, 52 digits

Some little knowledge about calculation accuracy in javascript (summary)

For those who have no contact, the above may be very vague to understand. It doesn’t matter. Next, we will use a case to explain the process in detail. First, let’s take a look at how the above-mentioned decimal number 8.25 is saved in JS. .

  • Decimal 8.25 will be converted into binary 1000.01;

  • Binary 1000.01 can be represented by binary scientific notation 1.00001 * 2^4;

  • 00001 * The decimal part 00001 (binary) of 2^4 is the mantissa (mantissa), and 4 (decimal) plus 1023 is the exponent (exponent) (I will explain why later Add 1023);

  • Next, the exponent 4 needs to be added to 1023 and converted to binary 10000000011;

  • Our decimal 8.25 is a positive Numbers, so the symbol is two-in-production indicated as 0

  • 8.25 The final binary preservation 0-1000000000011-00000000000000000000000000000000000000000 000 000 00000000000 00 数
# We add 0 if there are not enough digits;

  • We seem to have forgotten the integer part 1 in scientific notation obtained in step 2. This is because Javascript is used to make it more accurate. To maximize accuracy, this 1 is omitted, In this way, we can only save a (binary) 52-bit mantissa, but there are actually 53 (binary) bits;

  • The exponent part is 11 bits, and the range represented is [0 , 2047], since the exponent in scientific notation can be positive or negative, the intermediate number is 1023, [0,1022] is expressed as negative, [1024,2047] is expressed as positive, This also explains why the exponent in our scientific notation is stored with 1023 added.

  • 3. How does javascript read numbers

#We still use the binary of 8.25 0-10000000011-000010000000000000000000000000000000000000000000000 Let’s talk about

First we get the binary 1000000001 of the exponent part and convert it into decimal 1027. 1027 minus 1023 is our actual exponent 4;

  1. Get the mantissa part 000010000000000000000000000000000000000000000000000. The actual value is 0.00001 (the following 0 will not be written), and then add the 1 we ignored, and get 1.00001;

  2. Because the first digit is 0, so Our number is a positive number, so the scientific notation in binary is 1.00001 * 2^4, and then converted to decimal, we get our 8.25;

  3. IV. Looking at JavaScript accuracy issues from 0.1 0.2

Here we are about to enter our main topic. After understanding the previous principle explanation, this part will become easy to understand. . To calculate 0.1 0.2, you must first read these two floating point numbers.

0.1 is stored as a 64-bit binary floating point number.

Have you not forgotten the above steps?

First convert 0.1 into binary, the integer part is 0, and the decimal part is: 0001100110011001100110011001100110011...Hey, there is an infinite loop here, what should I do? Ignore it for now;

  1. The infinite loop binary number we get is expressed in scientific notation as 1.100110011001100110011001100110011... * 2^-4;

  2. The exponent bit is -4 1023 = 1019, and the conversion bit is an 11-digit binary number 01111111011;

  3. The mantissa bit is an infinite loop, but the double-precision floating point number stipulates 52 mantissa bits, so Those exceeding 52 bits will be omitted, and 1001100110011001100110011001100110011001100110011010

  4. will finally be obtained as a 64-bit binary floating point number of 0.1: 0-01111111011-100110011001100110 0110011001100110011001100110011010

同上,0.2存储为64位二进制浮点数:0-01111111100-1001100110011001100110011001100110011001100110011010

读取到两个浮点数的64为二进制后,再将其转化为可计算的二进制数

  1. 0.1转化为1.1001100110011001100110011001100110011001100110011010 * 2^(1019 - 1023)——0.00011001100110011001100110011001100110011001100110011010;

  2. 0.2转化为1.1001100110011001100110011001100110011001100110011010 * 2^(1020 - 1023)——0.0011001100110011001100110011001100110011001100110011010;

接着将两个浮点数的二进制数进行加法运算,得出0.0100110011001100110011001100110011001100110011001100111转化为十进制数即为0.30000000000000004

不难看出,精度缺失是在存储这一步就丢失了,后面的计算只是在不精准的值上进行的运算。

五. javascript如何解决精度问题出现的计算错误问题

对于小数或者整数的简单运算可如下解决:

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

如:0.1 + 0.2 通过函数处理后,相当于 (0.1 * 10 + 0.2 * 10) / 10

但是如同我们前面所了解的,浮点数在存储的时候就已经丢失精度了,所以浮点数乘以一个基数仍然会存在精度缺失问题,比如2500.01 * 100 = 250001.00000000003, 所以我们可以在以上函数的结果之上使用toFixed(),保留需要的小数位数。

一些复杂的计算,可以引入一些库进行解决


The above is the detailed content of Some little knowledge about calculation accuracy in javascript (summary). For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn