This article is divided into three parts
- Some typical problems of JS digital precision loss
- The reason for the loss of JS digital precision
- Solution (one object + one function)
Some typical problems of JS digital precision loss
1. Two simple floating-point numbers added
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
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)
It's been on the line. Chrome prices are inconsistent with other browsers
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 bits used to represent the sign bit
- 11 bits to represent the index
- 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.
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
The following is an object I have written that masks the precision of the decimal subtraction operation. Of course the converted integer still cannot exceed 9007199254740992.
/** * Floatobj contains subtraction four methods, to ensure that the floating-point operation does not lose precision * * We know that in the computer programming language there is a problem of precision loss (or rounding error) in floating-point counting, which is based on the fact that binary and implementation bit limits can not be limited. * The following decimal decimal corresponds 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 the computer is a finite width, such as JavaScript using 64 bits to store the numeric type, so the excess will be shed.
The part of the shed is the part of the lost precision. * * * * * * * * * * * * * * * * * * * * * * * * * * * * 0.1 + 0.2 = 0.30000000000000004 (0.00000 add/subtract/multiply/divide 000000004) * 0.2 + 0.4 = 0.6000000000000001 (more 0.0000000000001) * 19.9 * 100 = 1989.9999999999998 (Less 0.0000000000002 ) * * Floatobj.add (0.1, 0.2) >> 0.3 * floatobj.multiply (19.9, MB) >> 1990 * */var floatobj = function () {/* * 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 is * @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 * times + 0.5, 10 Ret.times = times Ret.num = intnum return ret}/* Core method to implement subtraction operation to ensure no loss of precision * thought: To enlarge decimal to Integer (multiply), perform arithmetic operations, and then reduce to decimal ( except) * * @param a {number} op arithmetic 1 * @param b {Number} count 2 * @param digits {number} precision, small points reserved, such as 2, which is reserved for two decimal places * @par Am OP {string} operation type, subtraction (add/subtract/multiply/divide) */function operation (A, B, digits, op) {var O1 = Tointe GER (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 ' Sub Tract ': result = o1.num-o2.num-break case ' multiply ': result = O1.num * O2.num break case ' divide ' : result = O1.num/o2.num break} return Result/max}//Subtraction four interface functionAdd (A, B, digits) {return operation (A, B, digits, ' add ')} function subtract (a, b, digits) {return operation (b, Digits, ' subtract '} function multiply (a, b, digits) {return operation (A, B, digits, ' multiply ')} function divID
E (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 = par Seint (DES, ten)/times return
des + '
}
The above is about JavaScript digital precision loss of all the content, analysis of typical problems, analysis of the reasons for the loss of digital precision, but also to share the solution, hoping to help everyone's learning.