A summary of JavaScript digital accuracy loss

Source: Internet
Author: User
Tags pow

This article is divided into three parts

    1. Some typical problems of JS digital precision loss
    2. The reason for the loss of JS digital precision
    3. Solution (one object + one function)

First, JS digital precision loss of some typical problems

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

The 16-and 17-digit numbers are equal.

And AS

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

Look at the results

The third view was overturned.

3. ToFixed will not be rounded (Chrome)

1.335.toFixed (2)//1.33

Firebug

There has been a discrepancy between the price in Chrome and the other browsers online.

Second, JS digital loss of precision reasons

The binary implementation of the computer and the number of bits limit cannot be expressed in finite numbers. Just like some irrational numbers can not be limited to express, such as Pi 3.1415926...,1.3333 ... such as JS follows the IEEE 754 specification, using double-precision storage (double precision), occupying a single bit.

Significance

    • 1 bits used to denote symbol bits
    • 11 bits to represent the exponent
    • 52-bit indicates mantissa

Floating-point numbers, such as

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

At this point can only imitate the decimal rounding, but the binary only 0 and 12, and then become 0 1 into. This is the computer in some floating-point arithmetic error, the root cause of the loss of precision.

The precision of a large integer is lost and the floating-point number is essentially the same, and the trailing digit is 52 bits maximum, so the maximum integer that can be accurately represented in JS is Math.pow (2, 53), and decimal is 9007199254740992.

Accuracy greater than 9007199254740992 may be lost

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

As a matter of fact

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

Results

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

For more in-depth analysis you can read this article (Long and smelly): What every computer scientist should Know about floating-point arithmetic

Third, the solution

For integers, the odds of a problem at the front end may be lower, after all, there is very little business need to use a large integer, as long as the result of the operation is not more than Math.pow (2, 53) will not lose precision.

For decimals, there is a lot of problems with the front end, especially in some e-commerce sites that involve amounts of data. Solution: Put the decimal place in the integer (multiplier), and then reduce back to the original multiple (in addition to multiples)

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

  

The following is an object that I have written to mask the loss of precision for fractional subtraction operations. Of course, the converted integer still cannot exceed 9007199254740992.

/** * Floatobj contains subtraction four methods to ensure that floating-point arithmetic does not lose precision * * We know that there is a loss of precision (or rounding error) in the calculation of floating-point numbers in the computer programming language, the root cause is that the binary and implementation bits limit some number cannot be limited representation * The following are binary representations of decimal decimals * 0.1 >> 0.0001 1001 1001 1001 ... (1001 Infinite Loop) * 0.2 >> 0.0011 0011 0011 0011 ... (0011 infinite loops) * The storage of each data type in the computer is a finite width, such as JavaScript uses 64-bit to store the number type, so the excess will go away. The part of the shed is the missing part of the precision. * * * * * * * * * * * * * * * * * * * * * * * * * * 0.1 + 0.2 = 0.30000000000000004 (0.00000000 000004) * 0.2 + 0.4 = = 0.6000000000000001 (more than 0.0000000000001) * 19.9 * 100 = 1989.9999999999998 (less than 0.0000000000002)     * * Floatobj.add (0.1, 0.2) >> 0.3 * floatobj.multiply (19.9, +) >> 1990 * */var floatobj = function () { /* * Determine if obj is an integer */function Isinteger (obj) {return Math.floor (obj) = = = obj}/* * Convert a floating-point number to An integer that returns an integer and a multiple.    such as 3.14 >> 314, multiples of * @param floatnum {number} decimal * @return {Object} * {times:100, num:314} */    function Tointeger (floatnum) {var ret = {times:0, num:0}    if (Isinteger (Floatnum)) {Ret.num = Floatnum return ret} var Strfi = Floatnum +        ' var dotpos = Strfi.indexof ('. ') var len = strfi.substr (dotpos+1). length var times = Math.pow (ten, len) var intnum = parseint (Floatnum * t IMEs + 0.5, ret.times = times Ret.num = intnum return ret}/* Core method, implements subtraction operation, ensures that no Lost precision * idea: Enlarge decimal to Integer (multiply), perform arithmetic operation, and then reduce to decimal (except) * @param a {number} operand 1 * @param b {Number} operand 2 * @param di    Gits {Number} precision, reserved decimal points, such as 2, which is reserved as two decimal places * @param op {string} operation type, with subtraction (add/subtract/multiply/divide) * */  function operation (A, B, digits, op) {var O1 = Tointeger (a) var O2 = Tointeger (b) var max = O1.times > o2.times? o1.times:o2.times var result = null switch (OP) {case ' add ': result = O1.num + O2.num break case ' subtract ': result = O1.num-o2.num break case ' multiply ': result = O1.num * O2.num b Reak case ' divide ': result = O1.num/o2.num break} return result /MAX}//Subtraction four interface function add (a, B, digits) {return operation (A, B, digits, ' add ')} function        Subtract (A, b, digits) {return operation (A, B, digits, ' subtract ')} 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, D Ivide:divide}} ();

The tofixed fixes are as follows

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

Related:

Http://0.30000000000000004.com

Http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

Related:

http://mathjs.org/
http://www.ituring.com.cn/article/73940
Https://en.wikipedia.org/wiki/IEEE_floating_point
http://modernweb.com/2014/02/17/what-every-javascript-developer-should-know-about-floating-points/
http://tool.oschina.net/hexconvert/
http://0.30000000000000004.com/
Http://demon.tw/copy-paste/javascript-precision.html

A summary of JavaScript digital accuracy loss

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.