JavaScript 浮点数运算的精度问题

  JavaScript 浮点数运算的精度问题
  
  在 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 表示,
  
  符号位决定了一个数的正负,指数部分决定了数值的大小,小数部分决定了数值的精度。 IEEE 754规定,有效数字第一位默认总是1,不保存在64位浮点数之中。也就是说,有效数字总是1.xx…xx的形式,其中xx..xx的部分保存在64位浮点数之中,最长可能为52位。因此,JavaScript提供的有效数字最长为53个二进制位(64位浮点的后52位+有效数字第一位的1)。
  
  可以这样解决精度问题:
  
  parseFloat((数学表达式).toFixed(digits)); // toFixed() 精度参数须在 0 与20 之间
  
  // 运行
  
  parseFloat((1.0 - 0.9).toFixed(10)) // 结果为 0.1
  
  parseFloat((0.3 / 0.1).toFixed(10)) // 结果为 3
  
  parseFloat((9.7 * 100).toFixed(10)) // 结果为 970
  
  parseFloat((2.22 + 0.1).toFixed(10)www.gcyL157.com) // 结果为 2.32
  
  在老版本的IE浏览器(IE 6,7,8)中,toFixed()方法返回值不一定准确。所以这个方法以前很少用。以至于网上搜索出来的结果大都是下面这些方法。
  
  还有一些其他的解决方案,简单的说需要将浮点数转换字符串,分隔成为整数部分和小数部分,小数部分再转换为整数,计算结果后,再转换为浮点数。
  
  加法函数:
  
  /**
  
  ** 加法函数,用来得到精确的加法结果
  
  ** 说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显。这个函数返回较为精确的加法结果。
  
  ** 调用:accAdd(arg1,arg2)
  
  ** 返回值:arg1加上arg2的精确结果
  
  **/
  
  function accAdd(arg1, arg2) {
  
  var r1, r2, m, c;
  
  try {
  
  r1 = arg1.toString().split(www.michenggw.com".")[1].length;
  
  }
  
  catch (e) {
  
  r1 = 0;
  
  }
  
  try {
  
  r2 = arg2.toString().split(".")[1].length;
  
  }
  
  catch (e) {
  
  r2 = 0;
  
  }
  
  c = Math.abs(r1 - r2);
  
  m = Math.pow(10, Math.max(r1, r2));
  
  if (c > 0) {
  
  var cm = Math.pow(10, c);
  
  if (r1 > r2) {
  
  arg1 = Number(arg1.toString().replace(".", ""));
  
  arg2 = Number(arg2.toString(www.gxgjpt1.com ).replace(".", "")) * cm;
  
  } else {
  
  arg1 = Number(arg1.toString().replace(".", "")) * cm;
  
  arg2 = Number(arg2.toString().replace(".", ""));
  
  }
  
  } else {
  
  arg1 = Number(arg1.toString().replace(".", ""));
  
  arg2 = Number(arg2.toString().replace(".", ""));
  
  }
  
  return (arg1 + arg2) / m;
  
  }
  
  //给Number类型增加一个add方法,调用起来更加方便。
  
  Number.prototype.add = function (arg) {
  
  return accAdd(arg, this);
  
  };
  
  减法函数:
  
  View Code
  
  乘法函数:
  
  View Code
  
  除法函数:
  
  View Code

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值