记录关于JavaScript 浮点数运算的精度问题

在做项目时,需要页面进行数据计算,简单的加法,对JavaScript来说就会出现错误了,例如alert(0.3-(0.5-0.1));结果不是-0.1而是-0.1

在 JavaScript 中整数和浮点数都属于 Number 数据类型,所有数字都是以 64 位浮点数形式储存,即便整数也是如此。 所以我们在打印  1.00 这样的浮点数的结果是 1 而非 1.00 。

JavaScript 里的数字是采用 IEEE 754 标准 的 64 位双精度浮点数。该规范定义了浮点数的格式,对于64位的浮点数在内存中的表示,最高的1位是符号位,接着的11位是指数,剩下的52位为有效数字,具体:

  • 第0位:符号位, s 表示 ,0表示正数,1表示负数;
  • 第1位到第11位:储存指数部分, e 表示 ;
  • 第12位到第63位:储存小数部分(即有效数字),f 表示,

解决方案:

使用 浮点数运算 toFixed() 方法;

有些浏览器存在误差问题,需要重写
  

  Number.prototype.toFixed = function(s) 
     { 
     changenum=(parseInt(this * Math.pow( 10, s ) + 0.5)/ Math.pow( 10, s )).toString(); 
     index=changenum.indexOf("."); 
     if(index<0&&s>0){ 
     changenum=changenum+"."; 
     for(i=0;i<s;i++){ 
     changenum=changenum+"0"; 
     } 
     }else { 
     index=changenum.length-index; 
     for(i=0;i<(s-index)+1;i++){ 
     changenum=changenum+"0"; 
     } 
     } 
     return changenum; 
     } 

自定义函数方法:
加法函数
 
 
JavaScript 代码:
  1. /**
  2. ** 加法函数,用来得到精确的加法结果
  3. ** 说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显。这个函数返回较为精确的加法结果。
  4. ** 调用:accAdd(arg1,arg2)
  5. ** 返回值:arg1加上arg2的精确结果
  6. **/
  7. function accAdd(arg1, arg2) {
  8. var r1, r2, m, c;
  9. try {
  10. r1 = arg1.toString().split(".")[1].length;
  11. }
  12. catch (e) {
  13. r1 = 0;
  14. }
  15. try {
  16. r2 = arg2.toString().split(".")[1].length;
  17. }
  18. catch (e) {
  19. r2 = 0;
  20. }
  21. c = Math.abs(r1 - r2);
  22. m = Math.pow(10, Math.max(r1, r2));
  23. if (c > 0) {
  24. var cm = Math.pow(10, c);
  25. if (r1 > r2) {
  26. arg1 = Number(arg1.toString().replace(".", ""));
  27. arg2 = Number(arg2.toString().replace(".", "")) * cm;
  28. } else {
  29. arg1 = Number(arg1.toString().replace(".", "")) * cm;
  30. arg2 = Number(arg2.toString().replace(".", ""));
  31. }
  32. } else {
  33. arg1 = Number(arg1.toString().replace(".", ""));
  34. arg2 = Number(arg2.toString().replace(".", ""));
  35. }
  36. return (arg1 + arg2) / m;
  37. }
  38.  
  39. //给Number类型增加一个add方法,调用起来更加方便。
  40. Number.prototype.add = function (arg) {
  41. return accAdd(arg, this);
  42. };
减法函数
 
 
JavaScript 代码:
  1. /**
  2. ** 减法函数,用来得到精确的减法结果
  3. ** 说明:javascript的减法结果会有误差,在两个浮点数相减的时候会比较明显。这个函数返回较为精确的减法结果。
  4. ** 调用:accSub(arg1,arg2)
  5. ** 返回值:arg1加上arg2的精确结果
  6. **/
  7. function accSub(arg1, arg2) {
  8. var r1, r2, m, n;
  9. try {
  10. r1 = arg1.toString().split(".")[1].length;
  11. }
  12. catch (e) {
  13. r1 = 0;
  14. }
  15. try {
  16. r2 = arg2.toString().split(".")[1].length;
  17. }
  18. catch (e) {
  19. r2 = 0;
  20. }
  21. m = Math.pow(10, Math.max(r1, r2)); //last modify by deeka //动态控制精度长度
  22. n = (r1 >= r2) ? r1 : r2;
  23. return ((arg1 * m - arg2 * m) / m).toFixed(n);
  24. }
  25.  
  26. // 给Number类型增加一个mul方法,调用起来更加方便。
  27. Number.prototype.sub = function (arg) {
  28. return accMul(arg, this);
  29. };
乘法函数
 
 
JavaScript 代码:
  1. /**
  2. ** 乘法函数,用来得到精确的乘法结果
  3. ** 说明:javascript的乘法结果会有误差,在两个浮点数相乘的时候会比较明显。这个函数返回较为精确的乘法结果。
  4. ** 调用:accMul(arg1,arg2)
  5. ** 返回值:arg1乘以 arg2的精确结果
  6. **/
  7. function accMul(arg1, arg2) {
  8. var m = 0, s1 = arg1.toString(), s2 = arg2.toString();
  9. try {
  10. m += s1.split(".")[1].length;
  11. }
  12. catch (e) {
  13. }
  14. try {
  15. m += s2.split(".")[1].length;
  16. }
  17. catch (e) {
  18. }
  19. return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m);
  20. }
  21.  
  22. // 给Number类型增加一个mul方法,调用起来更加方便。
  23. Number.prototype.mul = function (arg) {
  24. return accMul(arg, this);
  25. };
除法函数
 
 
JavaScript 代码:
  1. /**
  2. ** 除法函数,用来得到精确的除法结果
  3. ** 说明:javascript的除法结果会有误差,在两个浮点数相除的时候会比较明显。这个函数返回较为精确的除法结果。
  4. ** 调用:accDiv(arg1,arg2)
  5. ** 返回值:arg1除以arg2的精确结果
  6. **/
  7. function accDiv(arg1, arg2) {
  8. var t1 = 0, t2 = 0, r1, r2;
  9. try {
  10. t1 = arg1.toString().split(".")[1].length;
  11. }
  12. catch (e) {
  13. }
  14. try {
  15. t2 = arg2.toString().split(".")[1].length;
  16. }
  17. catch (e) {
  18. }
  19. with (Math) {
  20. r1 = Number(arg1.toString().replace(".", ""));
  21. r2 = Number(arg2.toString().replace(".", ""));
  22. return (r1 / r2) * pow(10, t2 - t1);
  23. }
  24. }
  25.  
  26. //给Number类型增加一个div方法,调用起来更加方便。
  27. Number.prototype.div = function (arg) {
  28. return accDiv(this, arg);
  29. };
或者使用js类库:
Math.js

官网:http://mathjs.org/

GitHub:https://github.com/josdejong/mathjs

decimal.js

为 JavaScript 提供十进制类型的任意精度数值。

官网:http://mikemcl.github.io/decimal.js/

GitHub:https://github.com/MikeMcl/decimal.js

big.js

官网:http://mikemcl.github.io/big.js

GitHub:https://github.com/MikeMcl/big.js/



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值