Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to solve the problem of operational accuracy of js

2025-01-29 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article is to share with you about the accuracy of js operation. The editor thinks it is very practical, so I share it with you. I hope you can get something after reading this article. Let's take a look at it with the editor.

We all know that using js to do calculation will definitely encounter the problem of calculation accuracy (or rounding error), but how to avoid these holes?

The reason for the loss of accuracy

Some of the binary implementation and bit limits of the computer cannot be expressed with a limited number. Just like some irrational numbers cannot be expressed finite, such as pi 3.1415926. , 1.3333... Wait. JavaScript uses 64-bit to store numeric types, so the excess will be dropped. What is left out is the part where the precision is lost.

The following is the binary representation of the decimal number

0.0001 1001 1001 1001. (infinite Loop) 1001 > > 0.0011 0011 0011 0011... (0011 infinite loop)

Solution

If you need more complex computing class libraries, you can consider well-known class libraries such as math.js

Floating point number (decimal)

For decimals, the probability of problems at the front end is still many, especially in some e-commerce websites involving data such as amount. Solution: put the decimal into an integer (multiplication), and then reduce it back to the original multiple (division multiple). After converting to an integer, the operation result can not exceed Math.pow (2Magee 53).

/ / 0.1 + 0.2 (0.1 / 10 + 0.2 / 10) / 10 = = 0.3 / / true

Floating point precision operation

/ * floatObj contains four methods of addition, subtraction, multiplication and division. Ensure that floating point operations do not lose precision * * method * * add / subtract / multiply / divide * * explame * * 0.1 + 0.2 = = 0.300000000000004 (more 0.000000000004) * 0.2 + 0.4 = = 0.60000000000001 (more 0.00000000001) * 19.9 * 100 = 1989.99999999998 (0.00000000002 less) * * floatObj.add (0.1) 1990 * / var floatObj = function () {/ * * determine whether obj is an integer * / function isInteger (obj) {return Math.floor (obj) = = obj} / * * convert a floating point number to an integer Returns integers and multiples. Such as 3.14 > 314 The multiple is 100 * @ 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 +''var dotPos = strfi.indexOf ('.') Var len = strfi.substr (dotPos+1). Length var times = Math.pow (10, len) var intNum = parseInt (floatNum * times + 0.5,10) ret.times = times ret.num = intNum return ret} / * * Core method to achieve addition, subtraction, multiplication and division, ensuring no loss of precision * idea: enlarge the decimal to integer (multiplication) and perform arithmetic operation Then reduce it to the decimal (except) * * @ param a {number} Operand 1 * @ param b {number} Operand 2 * @ param digits {number} precision, and the reserved decimal point, such as 2, is retained as a two-place decimal * @ param op {string} operation. There is addition, subtraction, multiplication and division (add/subtract/multiply/divide) * / function operation (a, b, digits, op) {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 switch (op) {case 'add': if (T1 = = T2) {/ / two decimal places are the same result = N1 + N2} else if (T1 > T2) {/ / o1 decimal place is greater than O2 result = N1 + N2 * (T1) / T2)} else {/ / o1 decimal place less than O2 result = N1 * (T2 / T1) + N2} return result / max case 'subtract': if (T1 = T2) {result = N1-N2} else if ( T1 > T2) {result = N1-N2 * (T1 / T2)} else {result = N1 * (T2 / T2)-N2} return result / max case 'multiply': result = (N1 * N2) / (T1 * T2) Return result case 'divide': result = (N1 / N2) * (T2 / T1) return result}} / / four interfaces function add (a) of addition, subtraction, multiplication and division 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, divide: divide}} ()

How to use it:

FloatTool.add (aformab); / / add floatTool.subtract (aformab); / / subtract floatTool.multiply (aformab); / / multiply floatTool.divide (aformab); / / divide

Super large integer

Although the above method can also be used for integers whose results do not exceed Math.pow (2Power53) (9007199254740992), if there is an excess, there may be some requirements such as batch numbers and segments in the actual scenario. Here I have also found a solution to go directly to the code.

Online operation: https://www.shen.ee/math.html

Function compare (p, Q) {while (p [0] ='0') {p = p.substr (1);} while (Q [0] ='0') {Q = q.substr (1);} if (p.length > q.length) {return 1;} else if (p.length)

< q.length) { return -1; } else { let i = 0; let a, b; while (1) { a = parseInt(p.charAt(i)); b = parseInt(q.charAt(i)); if (a >

B) {return 1;} else if (a

< b) { return -1; } else if (i === p.length - 1) { return 0; } i++; } }}function divide(A, B) { let result = []; let max = 9; let point = 5; let fill = 0; if (B.length - A.length >

0) {point + = fill = B.length-A. for;} for (let I = 0; I

< point; i++) { A += '0'; } let la = A.length; let lb = B.length; let b0 = parseInt(B.charAt(0)); let Adb = A.substr(0, lb); A = A.substr(lb); let temp, r; for (let j = 0; j < la - lb + 1; j++) { while (Adb[0] === '0') { Adb = Adb.substr(1); } if (Adb.length === lb) { max = Math.ceil((parseInt(Adb.charAt(0)) + 1) / b0); // 不可能取到这个最大值,1= 0; i--) { if (i === 0) { result.push(0); Adb += A[0]; A = A.substr(1); break; } else { temp = temp || multiply(B, i + ''); r = compare(temp, Adb); if (r === 0 || r === -1) { result.push(i); if (r) { Adb = reduce(Adb, temp); Adb += A[0]; } else { Adb = A[0]; } A = A.substr(1); break; } else { temp = reduce(temp, B); } } } temp = 0; } for (let i = 0; i < fill; i++) { result.unshift('0'); } result.splice(result.length - point, 0, '.'); if (!result[0] && result[1] !== '.') { result.shift(); } point = false; let position = result.indexOf('.'); for (let i = position + 1; i < result.length; i++) { if (result[i]) { point = true; break; } } if (!point) { result.splice(position); } result = result.join(''); return result;}function multiply(A, B) { let result = []; (A += ''), (B += ''); const l = -4; // 以支持百万位精确运算,但速度减半 let r1 = [], r2 = []; while (A !== '') { r1.unshift(parseInt(A.substr(l))); A = A.slice(0, l); } while (B !== '') { r2.unshift(parseInt(B.substr(l))); B = B.slice(0, l); } let index, value; for (let i = 0; i < r1.length; i++) { for (let j = 0; j < r2.length; j++) { value = 0; if (r1[i] && r2[j]) { value = r1[i] * r2[j]; } index = i + j; if (result[index]) { result[index] += value; } else { result[index] = value; } } } for (let i = result.length - 1; i >

0; iMel -) {result [I] + ='; if (result[ I] .length >-l) {result [i1] + = parseInt (result[ I] .slice (0, l)); result [I] = result.substr (l);} while (result[ I] .length)

< -l) { result[i] = '0' + result[i]; } } if (result[0]) { result = result.join(''); } else { result = '0'; } return result;}function add(A, B) { let result = []; (A += ''), (B += ''); const l = -15; while (A !== '' && B !== '') { result.unshift(parseInt(A.substr(l)) + parseInt(B.substr(l))); A = A.slice(0, l); B = B.slice(0, l); } A += B; for (let i = result.length - 1; i >

0; iMel -) {result [I] + ='; if (result[ I] .length >-l) {result [i1] + = 1; result [I] = result[ I] .substr (1);} else {while (result.length)

< -l) { result[i] = '0' + result[i]; } } } while (A && (result[0] + '').length >

-l) {result [0] = (result [0] +') .substr (1); result.unshift (parseInt (A.substr (l)) + 1); A = A.slice (0, l);} if (A) {while ((result [0] +') .length

< -l) { result[0] = '0' + result[0]; } result.unshift(A); } if (result[0]) { result = result.join(''); } else { result = '0'; } return result;}function reduce(A, B) { let result = []; (A += ''), (B += ''); while (A[0] === '0') { A = A.substr(1); } while (B[0] === '0') { B = B.substr(1); } const l = -15; let N = '1'; for (let i = 0; i < -l; i++) { N += '0'; } N = parseInt(N); while (A !== '' && B !== '') { result.unshift(parseInt(A.substr(l)) - parseInt(B.substr(l))); A = A.slice(0, l); B = B.slice(0, l); } if (A !== '' || B !== '') { let s = B === '' ? 1 : -1; A += B; while (A !== '') { result.unshift(s * parseInt(A.substr(l))); A = A.slice(0, l); } } while (result.length !== 0 && result[0] === 0) { result.shift(); } let s = ''; if (result.length === 0) { result = 0; } else if (result[0] < 0) { s = '-'; for (let i = result.length - 1; i >

0; result -) {if (result [I] > 0) {result [I]-= N; result [I-1] + +;} result [I] * =-1; result [I] + ='; while (result [I] .length

< -l) { result[i] = '0' + result[i]; } } result[0] *= -1; } else { for (let i = result.length - 1; i >

0; iMel -) {if (result [I] < 0) {result [I] + = N; result [I-1] -;} result [I] + =''; while (result [I] .length <-l) {result [I] ='0' + result [I] } if (result) {while ((result [0] = parseInt (result [0])) = 0) {result.shift ();} result = s + result.join ('');} return result;}

Usage: negative numbers cannot be used, and strings are best used for parameters.

Divide (AMagol B) / / Division multiply (AMagol B) / / multiplicative add (AMagol B) / / Additive reduce (Amena B) / / subtraction

Repair of toFixed

In Firefox / Chrome, toFixed does not round if the last place is 5.

1.35.toFixed (1) / / 1.4 correct 1.335.toFixed (2) / 1.33 error 1.3335.toFixed (3) / 1.333 error 1.33335.toFixed (4) / / 1.3334 correct 1.333335.toFixed (5) / / 1.33333 error 1.3333335.toFixed (6) / / 1.333333 error

There is no problem with the implementation of Firefox and Chrome, and the root cause is the loss of floating-point precision in the computer.

Repair method:

Function toFixed (num, s) {var times = Math.pow (10, s) var des = num * times + 0.5 des = parseInt (des, 10) / times return des +''} above is the problem of accuracy of js operation. The editor believes that there are some knowledge points that we may see or use in our daily work. I hope you can learn more from this article. For more details, please follow the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report