博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
js数值计算精度再次入坑
阅读量:6926 次
发布时间:2019-06-27

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

js数值类型计算一直有一个坑,就是关于计算精度的问题。在js中计算 0.1+0.2、0.3-0.1等运算时,会出现很惊人的一大串数值,相信很多人都遇到过

0.1+0.2  //0.300000000000000040.3-0.1  //0.19999999999999998复制代码

关于产生这个问题的原因,网上已经有很多说明了,大体就是js浮点类型精度的问题导致的,因此在计算的时候我们通常会采取一些方法,截取所需要的值。

回到正题,这次遇到的坑也是精度问题,但是不是加减法而是乘法,一个浮点数乘以10,结果也是惊人的长————————

0.68*10  //6.800000000000001复制代码

可能很多人遇到过乘法精度问题,但是我确实是第一次遇到这种问题。问题产生的背景是,后端返回一个浮点数m,前端在此基础上乘10,转换为“m折”字样展现在页面上。需求很简单,但是却有一个隐藏的坑。

其实要解决这个坑并不难,网上也有很多办法,此处列举几个:

1)toFixed方法

浮点数*10然后调用toFixed方法可以解决此问题,但是也有一个问题,就是会存在四舍五入的问题,如果要求准确的展示后台返回的数值,这个方法就会有缺陷。

(0.68*10).toFixed(2)  //此时没问题,结果为6.80(0.0686*10).toFixed(2)  //小数位数多的时候就会有四舍五入问题,此时结果为0.69复制代码

(2)将浮点数乘以10的倍数,再除以相应的10的倍数

这个方法也很常用,就是将浮点数转化为整数,在除以相应的倍数转换为浮点数。这个方法基本可以覆盖很大部分问题,但是一种方法不试用,就是浮点数的位数不确定的时候,无法准确判断乘以10的准确倍数。

0.68*1000/100   //此时结果正常,结果为6.8假如返回的浮点数不确定位数,但是依旧按乘1000/100方式计算0.00000068*1000/100   //结果又很给力了, 结果为0.000006799999999999999复制代码

(3)利用Math相关方法转换

此方法主要是利用Math.round和Math.pow方法对数据进行处理,借用网上的一个方法

function myFixed(a, b) {  return Math.round(a * Math.pow(10, b)) / Math.pow(10, b);}console.log(0.68*10);              //6.800000000000001console.log(myFixed(0.68*10, 2));  //6.8复制代码

4)字符串转换方法

最后说一下我们填坑的方法,因为此处对数值的应用只是将其转化为折扣数值,可以说是不需要进行运算处理的,因此采用了一个直截了当的字符串截取的方法,直接上代码:

//此方法考虑数值都是大于等于0的数值,并且对0和大于1的数值进行了展示(理论上折扣券不会出现0和大于1的情况)function discounts(discountNumber){      if (!discountNumber && discountNumber !== 0) {        return      }      const expPoint = /\./    let countString = String(discountNumber)      let discountString = ''      if(countString < 1 && expPoint.test(countString)){            let discountArr = countString.split('.')[1].split('')            if(discountArr.length === 1){                  discountString = discountArr[0]            }else{                  let discountStringFirst = discountArr[0]                  let discountStringSecond = discountArr.slice(1).join('')                  discountString = discountStringFirst + '.' + discountStringSecond        }    }else{            discountString = countString * 10      }      return discountString}discounts(0)     //0discounts(0.3)   //3discounts(0.68)  //6.8discounts(0.9)   //9discounts(1)     //10discounts(1.02)  //10.2复制代码

到此问题得到了解决,并且基本能覆盖到所有正常情况。

最后要说的是,关于数值计算精度问题在开发中一定要小心,稍有不慎就会掉入超长浮点数的坑里,在此也是记录并且告诉下自己,避免后面再次入坑。

转载于:https://juejin.im/post/5d00f01e518825382565c473

你可能感兴趣的文章
用ElasticSearch,LogStash,Kibana搭建实时日志收集系统
查看>>
MATLAB中-27开3次方得不到-3的原因
查看>>
一个格式化字符串的函数ToString
查看>>
I/O: std::ios_base::openmode
查看>>
排序算法(六)——希尔排序
查看>>
微信小程序:input输入框和form表单几种传值和取值方式
查看>>
Web安全测试工具小集
查看>>
spring mvc 404页面制作
查看>>
使用Swift模拟Window-LFU
查看>>
Android学习笔记(20):时钟(AnalogClock和TextClock)和计时器(Chronometer)
查看>>
我的Android进阶之旅------&gt;Android编译错误java.util.zip.ZipException: duplicate entry的解决方法...
查看>>
Python利用jieba获取中文词汇等
查看>>
Redhat 6.2安装Oracle 11gclient及遇到的问题分析
查看>>
-webkit-transform:translate3d(0,0,0)触发GPU加速,让网页动画更流畅
查看>>
【软件project】——软工视频总结
查看>>
markdown流程图语法
查看>>
ElasticSearch无法启动
查看>>
mysql explain 的type解释
查看>>
jQuery遍历方式
查看>>
C++环境编译使用sqlite数据库全过程
查看>>