博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[ JS 基础 ] JS 浮点数四则运算精度丢失问题 (3)
阅读量:6374 次
发布时间:2019-06-23

本文共 2257 字,大约阅读时间需要 7 分钟。

基于这个问题: ,我想应该也有一部分人没有认真对待过js中浮点数的四则运算出现的问题。

1.问题描述

示例代码:    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 是一门弱类型的语言,从设计思想上就没有对浮点数有个严格的数据类型,所以精度误差的问题就显得格外突出。

2.产生原因

Javascript采用了IEEE-745浮点数表示法(几乎所有的编程语言都采用),这是一种二进制表示法,可以精确地表示分数,比如1/2,1/8,1/1024。遗憾的是,我们常用的分数(特别是在金融的计算方面)都是十进制分数1/10,1/100等。二进制浮点数表示法并不能精确的表示类似0.1这样 的简单的数字,上诉代码的中的x和y的值非常接近最终的正确值,这种计算结果可以胜任大多数的计算任务:这个问题也只有在比较两个值是否相等时才会出现。

javascript的未来版本或许会支持十进制数字类型以避免这些舍入问题,在这之前,你更愿意使用大整数进行重要的金融计算,例如,要使用整数‘分’而不是使用小数‘元’进行货比单位的运算---------以上整理自《Javascript权威指南P37》

3. 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。

4.解决方案 (引自:)

为了解决浮点数运算不准确的问题,在运算前我们把参加运算的数先升级(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);       }   }

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

转载地址:http://dvnqa.baihongyu.com/

你可能感兴趣的文章
根据物流号查看物流信息
查看>>
jsp设置MIME类型
查看>>
python模拟自动登录网站(urllib2)
查看>>
Java 对文件的操作
查看>>
洛谷 题解 P3627 【[APIO2009]抢掠计划】
查看>>
2013年
查看>>
Oracle Hint
查看>>
Android 几种消息推送方案总结
查看>>
tempdb 相关总结
查看>>
Android开发人员应该选择哪种语言?
查看>>
Struts2中集合收集表单数据
查看>>
ceph安装过程
查看>>
安装Fast Search For Sharepoint 2010
查看>>
Lrucache缓存技术
查看>>
php if条件直接赋值,什么是条件赋值语句
查看>>
php preg replace报错,ECSHOP完美解决Deprecated: preg_replace()报错的问题
查看>>
linux centos 分区,CentOS 分区方案
查看>>
linux登录界面鼠标键盘失灵,在archlinux安装界面这卡住了,鼠标键盘失灵
查看>>
linux怎么查看F5地址,F5-npath模式-说明-linux上配置
查看>>
android把函数参数传递,Android Kotlin 将函数作为参数传递
查看>>