0.1+0.2 = 0.30000000000000004 0.1+0.2 is not equal to 0.3? Many people have encountered this problem, and the following details why it occurs.

Js number storage – floating point number storage

  • In JS, whether integers or decimals, there is only Number type, which complies with IEEE 754 standard and is represented by 64 bits, namely double precision floating point Number.

Hexadecimal conversion

  1. Binary to decimal

    11.01 --> 1*2^1 + 1*2^0 + 0*2^ {-1} + 1*2^ {-2} = 3.25
    Copy the code
  2. Decimal to binary

    • Integer: mod by two, and then in reverse order, high order to complement zero.
      2 --> 2 / 2 = 1 --- 0    1 / 2 = 0 --- 1To sort by theta10
      Copy the code
    • Decimals: multiply the number after the decimal point by 2, take the integer part of the result (1 or 0), then multiply the decimal part by 2 again, take the integer part of the result… And so on, until the small part is zero or the number of digits is enough.
      0.1:
      0.1 * 2 = 0.2 --- 0
      0.2 * 2 = 0.4 --- 0 
      0.4 * 2 = 0.8 --- 0
      0.8 * 2= __1.6__ -- __1__ __0.6__ *2 = 1.2 --- 1
      0.2 * 2 = 0.4 --- 0 
      
      0.1 -> 0.0001100110011001. (Infinite loop)Copy the code

Floating point Numbers

  1. The formula for calculating floating point numbers

  1. 64-bit floating point number

    • Bit 0: sign bit, 0 for a positive number and 1 for a negative number (s).
    • Places 1 to 11: Places 11, storage index part (e)
    • Digits 12 to 63: Digits 52 store decimal parts (i.e., significant digits) (m)
  2. E is an unsigned integer that ranges from 0 to 2047 because it contains 11 digits. However, exponents in scientific notation can be negative, so the convention is to subtract a middle number 1023, where [0,1022] is negative and [1024,2047] is positive.

  3. Such as: 4.5

    • Convert to binary: 100.1
    • Convert to 1.001 * 2^2 according to the formula above
    • M is 001, e is 1023 + 2 = 1025, s is 0,1 can be omitted
  4. XXX * 2^e. XXX is stored in m. The maximum value of M is 52 bits, and the excess bits will be discarded. MAX_SAFE_INTEGER == math.pow (2,53) -1, which is 53 because there is a 1 in front of it.

  5. What happens when a greater than number in JS is greater than 2^53?

     (2^53.2^54) and can only be exact even numbers (2^54.2^55), can only be expressed accurately4A multiple... Skip more in turn2A multiple ofCopy the code

    MAX_SAFE_INTEGER math.pow (2, 53), which converts to binary is 1 and 53 0’s, and 53 0’s are omitted in m, which has only 52 bits, so the last 0’s are dropped. Math.pow(2, 53) + 1, which translates to 1 + 53 zeros in binary, the same as Math.pow(2, 53).

    Math.pow(2.53) = = =Math.pow(2.53) + 1  // true
    
    // todo why? How to intercept more than 52 bits?
     console.log((Math.pow(2.53)).toString(2))
     100000000000000000000000000000000000000000000000000000
    
     console.log((Math.pow(2.53) + 1).toString(2))
     100000000000000000000000000000000000000000000000000000
    
     console.log((Math.pow(2.53) + 2).toString(2))
     100000000000000000000000000000000000000000000000000010
    
    console.log((Math.pow(2.53) + 3).toString(2))
     100000000000000000000000000000000000000000000000000100
    
     console.log((Math.pow(2.53) + 4).toString(2))
    
     100000000000000000000000000000000000000000000000000100
    
     console.log((Math.pow(2.53) + 5).toString(2))
     100000000000000000000000000000000000000000000000000100
    
     console.log((Math.pow(2.53) + 6).toString(2))
     100000000000000000000000000000000000000000000000000110
    Copy the code
  6. Since E is 1023, the largest integer that can be represented is 2 to the 1024 minus 1, which is the largest integer that can be represented. But you can’t calculate it that way, because 2 to the 1024 becomes Infinity.

    The initial value of Infinity is number.positive_infinity. Infinity is greater than any value.

0.1 + 0.2! = = 0.3

  1. 0.1 and 0.2 are converted to binary

    0.1 -> 0.0001100110011001. (Infinite loop)0.2 -> 0.0011001100110011. (Infinite loop)Copy the code

    Exceeds the interception, resulting in precision loss.

  2. In order operations, the decimal points add up to them, resulting in a loss of precision.

    0.0100110011001100110011001100110011001100110011001100 
    Copy the code

    The result in decimal is 0.30000000000000004

So: 0.1 + 0.2 === 0.30000000000000004. Other decimal calculations yield similar results.

Why does x = 0.1 get 0.1

  • The resulting 0.1 is not a real 0.1, it is a browser manipulation.

  • As mentioned above, the maximum number of bits in M is 52, 2^53=9007199254740992, corresponding to the mantissut of scientific count is 9.007199254740992, which is also the maximum precision that JS can represent. It has a length of 16, so you can use toPrecision(16) to approximate the accuracy. If you exceed the accuracy, you will automatically round it up.

  • So: 0.10000000000000000555 toPrecision (16) = 0.1000000000000000, remove just after the zero at the end of 0.1

ToPrecision and toFixed

  1. Common ground: Numbers turned into strings for display.

  2. The difference between

    • ToPrecision is the processing precision, the precision from left to right from the first non-zero number counting.
    • ToFixed is the number of digits after the decimal point, counting from the decimal point.
  3. Problem with rounding with toFixed: 1.005. ToFixed (2) returns 1.00 instead of 1.01. Cause: The actual corresponding number of 1.005 is 1.00499999999999989, which is all rounded off. Solution: Use the rounding function math.round () to handle.

    So do not use these two methods in the calculation process, only for the results of the presentation.

Solve accuracy problems

Errors occur in base-conversion operations.

  1. The simplest way is to convert it to an integer operation. Integers (up to the maximum safe number) do not produce errors.

  2. Third party libraries: math.js, big.js, etc

  3. It’s very strict with numbers, so you can throw parameters to the back end, let the back end do the calculation, and give you the result back.

reference

  1. 0.1 + 0.2 does not equal 0.3? Why does JavaScript have this “slutty” operation?
  2. Number-plus and subtraction crisis — Why did this happen?
  3. JS numerical accuracy
  4. Catch the small tail of data – JS floating point traps and solutions
  5. JS digital storage problem