美文网首页
JavaScript 浮点运算精度问题

JavaScript 浮点运算精度问题

作者: 九毫 | 来源:发表于2017-01-13 15:31 被阅读0次

JavaScript 浮点运算精度问题


JavaScript浮点运算存在精度问题,本文阐述问题的产生原因以及解决方法

问题描述


示例:

var x = 0.3 - 0.2; //30美分减去20美分
var y = 0.2 - 0.1; //20美分减去10美分
x == y; // =>false,两值不相等
x == 0.1; // =>false,真实值为:0.09999999999999998
y == 0.1; // =>true

这个问题并不只是在Javascript中才会出现,任何使用二进制浮点数的编程语言都会有这个问题,只不过在 C++/C#/Java 这些语言中已经封装好了方法来避免精度的问题,而 JavaScript 是一门弱类型的语言,从设计思想上就没有对浮点数有个严格的数据类型,所以精度误差的问题就显得格外突出。

产生原因


Javascript采用了IEEE-745浮点数表示法(几乎所有的编程语言都采用),这是一种二进制表示法,可以精确地表示分数,比如1/2,1/8,1/1024。遗憾的是,我们常用的分数(特别是在金融的计算方面)都是十进制分数1/10,1/100等。二进制浮点数表示法并不能精确的表示类似0.1这样 的简单的数字,上诉代码的中的x和y的值非常接近最终的正确值,这种计算结果可以胜任大多数的计算任务:这个问题也只有在比较两个值是否相等时才会出现。 javascript的未来版本或许会支持十进制数字类型以避免这些舍入问题,在这之前,你更愿意使用大整数进行重要的金融计算,例如,要使用整数‘分’而不是使用小数‘元’进行货比单位的运算---------以上整理自《Javascript权威指南P37》

0.1+0.2的计算


首先,我们要站在计算机的角度思考 0.1 + 0.2 这个看似小儿科的问题。我们知道,能被计算机读懂的是二进制,而不是十进制,所以我们先把 0.1 和 0.2 转换成二进制看看:

0.1 => 0.0001 1001 1001 1001…(无限循环)
0.2 => 0.0011 0011 0011 0011…(无限循环)

双精度浮点数的小数部分最多支持 52 位,所以两者相加之后得到这么一串 0.0100110011001100110011001100110011001100110011001100 因浮点数小数位的限制而截断的二进制数字,这时候,我们再把它转换为十进制,就成了 0.30000000000000004。

解决方案


为了解决浮点数运算不准确的问题,在运算前我们把参加运算的数先升级(10的X的次方)到整数,等运算完后再降级(0.1的X的次方)。

//加法
Number.prototype.add = function(arg){
  var r1,r2,m;
  try{r1=this.toString().split(".")[1].length}catch(e){r1=0}
  try{r2=arg.toString().split(".")[1].length}catch(e){r2=0}
  m=Math.pow(10,Math.max(r1,r2))
  return (this*m+arg*m)/m
}
//减法
Number.prototype.sub = function (arg){
  return this.add(-arg);
}

//乘法
Number.prototype.mul = function (arg)
{
  var m=0,s1=this.toString(),s2=arg.toString();
  try{m+=s1.split(".")[1].length}catch(e){}
  try{m+=s2.split(".")[1].length}catch(e){}
  return Number(s1.replace(".",""))*Number(s2.replace(".",""))/Math.pow(10,m)
}

//除法
Number.prototype.div = function (arg){
  var t1=0,t2=0,r1,r2;
  try{t1=this.toString().split(".")[1].length}catch(e){}
  try{t2=arg.toString().split(".")[1].length}catch(e){}
  with(Math){
  r1=Number(this.toString().replace(".",""))
  r2=Number(arg.toString().replace(".",""))
    return (r1/r2)*pow(10,t2-t1);
  }
}

大家以后在自己的代码中遇到浮点数要想起js运算的这样的一个特性,避免不必要的错误!

相关文章

  • JavaScript 浮点运算精度问题

    JavaScript 浮点运算精度问题 JavaScript浮点运算存在精度问题,本文阐述问题的产生原因以及解决方...

  • JavaScript浮点数的精度问题深究

    JavaScript浮点数的精度问题 javascript浮点数的精度问题是老生常谈了,但往往只知道0.1 + 0...

  • 2.理解JavaScript的浮点数

    JavaScript中所有的数字都是双精度浮点数 JavaScript不会直接将操作数作为浮点数进行运算,而是会将...

  • 计算机组成原理:浮点精度运算不精确的原因

    为什么浮点精度运算会有问题 我们平常使用的编程语言大多都有一个问题——浮点型精度运算会不准确。比如 笔者在测试的时...

  • javaScript-02

    运算符 算数运算符 概念:算术运算使用的符号,用于执行两个变量或值的算术运算。 浮点数的精度问题浮点数值的最高精度...

  • JS中如何理解浮点数?

    本文由云+社区发表 相信大家在平常的 JavaScript 开发中,都有遇到过浮点数运算精度误差的问题,比如 co...

  • iOS开发浮点数计算精度问题

    1、浮点数运算带来的问题 在日常工作中涉及到浮点数(float、double)的运算 2、浮点数运算精度的解决方案...

  • JavaScript 浮点数运算的精度问题

    http://www.css88.com/archives/7340

  • iOS浮点运算精度问题

    无论是double还是float ,CPU位数都是有限的!而浮点数,理论上是无限长的!所以普通的浮点类型,进行运算...

  • js浮点运算

    前言 在项目开发过程中发现浮点数的运算会出现精度问题,尤其是乘除运算。产生浮点数计算精度不准确的原因: 在计算机角...

网友评论

      本文标题:JavaScript 浮点运算精度问题

      本文链接:https://www.haomeiwen.com/subject/hyjsbttx.html