JavaScript solves decimal subtraction precision loss scheme _javascript skills

Source: Internet
Author: User
Tags arithmetic pow reserved

Reason: JS in accordance with the 2 to deal with decimal subtraction, on the basis of arg1 arg2 precision extension or reverse expansion matching, so will appear as follows.

JavaScript (JS) decimal point subtraction problem, is a JS bug such as 0.3*1 = 0.2999999999, the following list can be perfect to find the corresponding accuracy of the four JS algorithm

function Accdiv (arg1,arg2) {var t1=0,t2=0,r1,r2; Try{t1=arg1.tostring (). Split (".") [1].length}catch (e) {} try{t2=arg2.tostring (). Split (".") [1].length}catch (e) {} with (Math) {R1=number (arg1.tostring (). Replace (".", ")) R2=number (Arg2.tostring (). Replace (". " 
 , "")) return Accmul ((R1/R2), pow (10,T2-T1)); 
 }///multiplication function Accmul (arg1,arg2) {var m=0,s1=arg1.tostring (), s2=arg2.tostring (); Try{m+=s1.split (".") [1].length}catch (e) {} try{m+=s2.split (".") [1].length}catch (e) {} return Number (S1.replace (".", "")) *number (S2.replace (".", ""))/math.pow (10,M)}//addition function AC 
CADD (arg1,arg2) {var r1,r2,m; Try{r1=arg1.tostring (). Split (".") [1].length}catch (e) {r1=0} try{r2=arg2.tostring (). Split (".") 
 [1].length}catch (e) {r2=0} m=math.pow (10,math.max (R1,R2)) return (arg1*m+arg2*m)/m}//Subtraction function subtr (ARG1,ARG2) { 
 var r1,r2,m,n; Try{r1=arg1.tostring (). Split (".") [1].length}catch (e) {r1=0} try{r2=arg2.tostring (). Split (".") [1].length}catch (e) {r2=0} m=math.pow (10,math. Max (R1,R2)); 
 N= (R1>=R2) r1:r2; 
Return ((arg1*m-arg2*m)/m). ToFixed (n);  }

Here's a concrete analysis of the loss of digital precision in JavaScript.

Some typical problems of JS digital precision loss

1. Two simple floating-point numbers added

0.1 + 0.2!= 0.3/True

Firebug

This is really not a Firebug problem, you can try it with alert (haha joking).

Look at the results of Java operations

And look at Python.

2. Large integer operation

9999999999999999 = 10000000000000001//?

Firebug

16 digits and 17 digits are equal.

And AS

var x = 9007199254740992
x + 1 = x//?

Look at the results

The three views were again overturned.

3. ToFixed not rounded (Chrome)

1.335.toFixed (2)//1.33

Firebug

There has been an inconsistency between the price in Chrome and other browsers because of toFixed compatibility issues

Second, JS digital loss of precision reasons

The binary implementation of the computer and the limit of the number of digits cannot be expressed in a limited way. Just like some irrational number can not be limited to express, such as Pi 3.1415926...,1.3333 ... Wait JS follows the IEEE 754 specification, using double storage (double precision) to occupy the bit. As shown in figure

Significance

    1. 1 bits used to represent the sign bit
    2. 11 bits to represent the index
    3. 52 digits indicates mantissa

Floating point numbers, such as

0.1 >> 0.0001 1001 1001 1001 ... (1001 Infinite cycle)
0.2 >> 0.0011 0011 0011 0011 ... (0011 infinite loops)

At this time can only imitate decimal rounding, but the binary only 0 and 12, and then into 0 homes 1 into. This is the basic reason of error and loss precision in some floating point counting in computer.

The accuracy of large integers is lost and floating-point numbers are essentially the same, the maximum number of digits is 52 bits, so the most accurate representation of JS is Math.pow (2, 53), Decimal is 9007199254740992.

Greater than 9007199254740992 may lose precision

9007199254740992   >> 10000000000000...000//Total 53 0
9007199254740992 + 1 >> 10000000000000...001// Middle 52 0
9007199254740992 + 2 >> 10000000000000...010//Middle 51 0

As a matter of fact

9007199254740992 + 1//Lost
9007199254740992 + 2//not lost
9007199254740992 + 3//missing
9007199254740992 + 4//Not lost

Results as shown

Above, you can know that seemingly poor numbers, in the computer's binary representation is infinite, due to the number of storage limit so there is "shed", precision loss occurred.

Want to know more in-depth analysis can read this paper (long and smelly): What Every Computer scientist Should Know about floating-point arithmetic

Third, the solution

for integers, the probability of a front end problem may be lower, after all, few business needs to use a large integer, as long as the result of the operation does not exceed Math.pow (2, 53) will not lose precision.

For decimals, the probability of the front-end problem is still a lot of, especially in some of the electronic business site involved in the amount of data. Solution: Put the decimal place Integer (multiplier), and then reduce back to the original multiple (in addition to multiple)

0.1 + 0.2
(0.1*10 + 0.2*10)/= = 0.3/True

Here I write an object that masks the accuracy of the decimal subtraction operation. Of course the converted integer still cannot exceed 9007199254740992.

The/**  * Floatobj contains subtraction four methods to ensure that floating-point operations do not lose precision  *  * We know that there is a problem of precision loss (or rounding error) in floating-point counting in the computer programming language. The root cause is binary and implementation-bit limits. Some numbers cannot be limited to represent  * below is a decimal decimal corresponding to the binary representation  *      0.1 >> 0.0001 1001 1001 1001.. (1001 Infinite cycle)  *      0.2 >> 0.0011 0011 0011 0011 ... (0011 infinite loops) The storage of each data type in a  * computer is a limited width, for example, JavaScript uses 64 bits to store the numeric type, so the excess is shed.
The part of the shed is the part of the lost precision.  *  * * * * *  *  add/subtract/multiply/divide  *  * * * explame * *  *  0 .1 + 0.2 = 0.30000000000000004 (more 0.00000000000004)  *  0.2 + 0.4 = = 0.6000000000000001  (more than 0.0000000000 001)  *  19.9 * 100 = 1989.9999999999998 (less 0.0000000000002)  *  * Floatobj.add (0.1, 0.2) >> 0 .3  * floatobj.multiply (19.9) >> 1990  *  */var floatobj = function () {   &nbsp
;     /*      * to determine if obj is an integer      */    function Isinteger (obj) {        return Math.floor (obj) = = obj               /*       * converts a floating-point number to an integer and returns an integer and a multiple. such as 3.14 >> 314, multiples are      * @param floatnum {number} decimal      * @
return {object}      *   {times:100, num:314}      */     function Tointeger (floatnum) {        var ret = { Times:1, num:0}         if (Isinteger (floatnum)) {             ret.num = Floatnum              return ret                   var strfi  = floatnum + "' &Nbsp;       var Dotpos = Strfi.indexof ('. ')          var len    = Strfi.substr (dotpos+1). Length          var times  = Math.pow (ten, len)         var intNum = ParseInt ( Floatnum * times + 0.5 (a)         ret.times  = times    & nbsp;    ret.num    = Intnum          return ret     }          /*       * core method, to achieve subtraction operation, to ensure that no loss of precision      * idea: To enlarge the decimal number to an integer (multiply), for arithmetic operations, and then reduced to decimal (except)       *      * @param a {number} op arithmetic 1      * @param b {Number}
Op count 2      * @param digits {number} precision, small points reserved, such as 2, which is reserved for two decimal places     * @param op {string} operation type, subtraction (add/subtract/multiply/divide)       *      */    function operation (A, B, digits, op) { & Nbsp;      var O1 = Tointeger (a)         var O2 = Tointeger (b)         var n1 = O1.num          var n2 = o2.num         var T1 = o1.times          var t2 = o2.times         var max = t1 > t2? T1:t2         var result = null        & Nbsp;switch (OP) {            case ' Add ':                   if (T1 = = t2) {//two decimal digits same                      result = n1 + n2                 &NBSP} else if (T1 > T2) {//O1 decimal bit greater than O2       &NB Sp;             result = n1 + N2 * (t1/t2)  &
NBSP;             &NBSP} else {//O1 decimal bit less than O2                      result = N1 * (t2/t1) + N2                  }                  return Result/max          &NBSp;  case ' Subtract ':                  if (t1 = = t2) {                     result = N1-n2                 &NBSP} else if (T1 > t2) {                     result = n1-n2 * (t1/t2)                 &NBSP} else {                     result = N1 * (T2/ T1)-n2                                   return Result/max             case ' multiply ':                  result = (N1 * n2)/(T1 * T2)                 return Result             case ' divide ':                  result = (n1/n2) * (T2/T1)                  return result         &NBSP}     }           //subtraction Four Interfaces     function Add (a, B, digits) {         return operation (A, B, digits, ' add ')     }     funCtion Subtract (A, b, digits) {        return operation (A, B, digits, ' Subtract ')    &nbsp}     function Multiply (a, b, digits) {         return operation (A, B, digits, ' multiply ')     }      function Divide (A, B, digits) {        return operation (A, B, Digits, ' divide ')     }          //exports      return {        add:add,          subtract:subtract,         multiply:multiply,          divide:divide     }} ();

Tofixed Repair is as follows

ToFixed Repair
function toFixed (num, s) {
var times = Math.pow (s)
var des = num * times + 0.5
Des = parseint (DES, ten)/times return
des + '
}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.