怎么解决javascript数字计算丢失精度问题?

 4855

怎么解决javascript数字计算丢失精度问题?


js数字计算丢失精度问题解决方案

计算机世界里,数字的计算,所有语言都会丢失精度,所以没有万全之策,但在人力范围内,尽量解决。

网上找了一部分代码,发现是有问题的,比如:

  1. //加法 
  2. Number.prototype.myAdd = function(arg2) {
  3.     var arg1 = this;
  4.     if (isNaN(arg2)) {
  5.         return arg2;
  6.     }
  7.     var r1, r2, m;
  8.     try { r1 = arg1.toString().split(".")[1].length } catch (e) { r1 = 0 }
  9.     try { r2 = arg2.toString().split(".")[1].length } catch (e) { r2 = 0 }
  10.     m = Math.pow(10, Math.max(r1, r2))
  11.     return (arg1 * m + arg2 * m) / m
  12. }
  13. //减法 
  14. Number.prototype.mySub = function(arg2) {
  15.     var arg1 = this;
  16.     if (isNaN(arg2)) {
  17.         return arg2;
  18.     }
  19.     var r1, r2, m, n;
  20.     try { r1 = arg1.toString().split(".")[1].length } catch (e) { r1 = 0 }
  21.     try { r2 = arg2.toString().split(".")[1].length } catch (e) { r2 = 0 }
  22.     m = Math.pow(10, Math.max(r1, r2));
  23.     n = (r1 >= r2) ? r1 : r2;
  24.     return ((arg1 * m - arg2 * m) / m).toFixed(n);
  25. }
  26. //乘法 
  27. Number.prototype.myMul = function(arg2) {
  28.     var arg1 = this;
  29.     if (isNaN(arg2)) {
  30.         return arg2;
  31.     }
  32.     var m = 0,
  33.         s1 = arg1.toString(),
  34.         s2 = arg2.toString();
  35.     try { m += s1.split(".")[1].length } catch (e) {}
  36.     try { m += s2.split(".")[1].length } catch (e) {}
  37.     return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m)
  38. }
  39. // 除法
  40. Number.prototype.myDiv = function(arg2) {
  41.     var arg1 = this;
  42.     if (isNaN(arg2)) {
  43.         return arg2;
  44.     }
  45.     var t1 = 0,
  46.         t2 = 0,
  47.         r1, r2;
  48.     try { t1 = arg1.toString().split(".")[1].length } catch (e) {}
  49.     try { t2 = arg2.toString().split(".")[1].length } catch (e) {}
  50.     with(Math) {
  51.         r1 = Number(arg1.toString().replace(".", ""))
  52.         r2 = Number(arg2.toString().replace(".", ""))
  53.         return (r1 / r2).myMul(pow(10, t2 - t1))
  54.     }
  55. }

在计算一些特殊的数字时,仍然有问题:

比如加法:

  1. 268.34.myDiv(0.83);//321.7505995203837

所以还要优化

我重新做了一版:

  1. var operationNumber = function (arg1,arg2,operator) {
  2.     var oper=['+','-','*','/'];
  3.     // 不合法的运算
  4.     if (isNaN(arg1)||isNaN(arg2)||oper.indexOf(operator)<0) {
  5.         return NaN;
  6.     }
  7.     // 除以0
  8.     if (operator==='/'&&Number(arg2)===0) {
  9.         return Infinity;
  10.     }
  11.     // 和0相乘
  12.     if (operator==='*'&&Number(arg2)===0) {
  13.         return 0;
  14.     }
  15.     // 相等两个数字相减
  16.     if ((arg1===arg2||Number(arg1)===Number(arg2))&&operator==='-') {
  17.         return 0;
  18.     }
  19.     var r1, r2, max,_r1,_r2;
  20.     try { r1 = arg1.toString().split(".")[1].length } catch (e) { r1 = 0 }
  21.     try { r2 = arg2.toString().split(".")[1].length } catch (e) { r2 = 0 }
  22.     max = Math.max(r1, r2)
  23.     _r1 = max-r1;
  24.     _r2 = max-r2;
  25.     if (_r1!==0) {
  26.         arg1=arg1+'0'.repeat(_r1)
  27.     }
  28.     if (_r2!==0) {
  29.         arg2=arg2+'0'.repeat(_r2)
  30.     }
  31.     arg1 = Number(arg1.toString().replace('.',''))
  32.     arg2 = Number(arg2.toString().replace('.',''))
  33.     var r3 = operator==='*'?(max*2):(operator==='/'?0:max);
  34.     var newNum = eval(arg1+operator+arg2);
  35.     if (r3!==0) {
  36.         var nStr = newNum.toString();
  37.         nStr = nStr.replace(/^-/,'');
  38.         if (nStr.length<r3+1) {
  39.             nStr = '0'.repeat(r3+1-nStr.length)+nStr;
  40.         }
  41.         nStr = nStr.replace(new RegExp('(\\\d{'+r3+'})$'),'.$1');
  42.         if (newNum<0) {
  43.             nStr = '-'+nStr;
  44.         }
  45.         newNum = nStr*1;
  46.     }
  47.     return newNum;
  48. }
  49. //加法 
  50. Number.prototype.myAdd = function(arg2) {
  51.     return operationNumber(this,arg2,'+');
  52. }
  53. //减法 
  54. Number.prototype.mySub = function(arg2) {
  55.     return operationNumber(this,arg2,'-');
  56. }
  57. //乘法 
  58. Number.prototype.myMul = function(arg2) {
  59.     return operationNumber(this,arg2,'*');
  60. }
  61. // 除法
  62. Number.prototype.myDiv = function(arg2) {
  63.     return operationNumber(this,arg2,'/');
  64. }

如果你发现了bug,评论区及时反馈,我及时跟进修复。


本文网址:https://www.zztuku.com/detail-7839.html
站长图库 - 怎么解决javascript数字计算丢失精度问题?
申明:如有侵犯,请 联系我们 删除。

评论(0)条

您还没有登录,请 登录 后发表评论!

提示:请勿发布广告垃圾评论,否则封号处理!!

    编辑推荐