ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

js小数点计算丢失精度

2022-03-07 17:34:29  阅读:226  来源: 互联网

标签:number decimal 小数点 js 丢失 小数 精度 math


  有时需求中会有前端校验输入数字金额的时候,判断,几个输入框的金额合计是否大于小于或等于某个整数,在输入的值可以为小数的时候,很容易就出现js小数点计算丢失精度问题。比如下图

  js高级程序设计(我这版是第3版)在3.4.5Number类型这节中就谈到了这个现象,原话是:

    关于浮点数值计算会产生摄入误差的问题,有一点需要明确:这是使用基于IEEE754数值的浮点计算的通病,ESMAScript并非独此一家,其他使用相同数值格式的语言也存在这个问题。

  所以即使浮点数值的最高精度是17位小数,但在进行算术计算时其精度远远不如整数。

  1.使用toFixed(x)方法,x为必需,规定小数的位数,是 0 ~ 20 之间的值,包括 0 和 20,如果省略了该参数,将用 0 代替。

  比如:

   但是这种方法的局限性是不能使用toFixed(x)去进行舍入操作。因为IEEE754标准规定的浮点数取整算法是银行家舍入法,即四舍六入五留双法:四舍六入五考虑,五后非零就进一,五后为零看奇偶,五前为偶应舍去,五前为奇要进一。

  早期的时候似乎在不同浏览器会有不同的表现,但是现在基本上大部分浏览器都是toFixed(x)遇5不会进1,而是直接舍去,可能也和chrome内核一家独大有关系。在Chrome浏览器中的控制台表现如下:

  精度只能用于所有操作数中最多小数位的精度计算,即toFixed(x)中的x必须大于等于最多小数位操作数的小数位数量,否则就会丢失精度。

  2.使用第三方库

  比如Math.js,decimal.js,使用方法大同小异,详情见:

  https://www.npmjs.com/package/mathjs

  https://www.npmjs.com/package/decimal.js/v/3.0.0

  以vue2.x为例:

  先npm install mathjs / decimal.js

  然后在main.js中引入,以ES模块规范为例:

  math.js是这样使用的:(详见math.js文档:https://mathjs.org/docs/index.html)

import * as math from "mathjs";

const config = {
  epsilon: 1e-12,
  matrix: 'Matrix',
  number: 'number', //运算时需要精度准确时此处需配置为BigNumber
  precision: 64, //仅在number类型为BigNumbers生效
  predictable: false,
  randomSeed: null //选项设置为种子伪随机数生成,使其成为确定性的。
}
const math = create(all, config);

let number = math.add(math.bignumber(0.1), math.bignumber(0.2)); //操作数中至少要有一个调用bignumber()

  decimal.js是这样使用的:(详见decimal.js文档:http://mikemcl.github.io/decimal.js/)

import { Decimal } from 'decimal.js';

let number = new Decimal(0.11).add(new Decimal(0.29));

其他

  本来到前面就到尾声了,但是这里还是需要啰嗦一下,我还看过一些博客还提到一个方法或是自己封装的方法,其核心是先将小数*10的n次方放大为整数,只要最终结果在Number类型边界之内的整数运算是不会有精度误差的,然后再将整数的运算结果除于10的n次方就得到最终的结果。但是,这个方法没写好也是存在问题的,就比如前面举的例子:0.07*100,结果就不是7。因为只有少数几个小数可以被浮点数精确表示,比如0.25的N次方,或是0.75的n次方,其他的小数基本都是近似数。其实我也很纳闷0.06,0.08也都是近似数,但是他们相乘100结果分别就是6,8。有些博主通过这个方法封装的方法都没考虑到这块,所以在相乘放大过程中就已经出错了,但是如果在放大缩小过程中能控制住精度,也仍不失为一个解决问题的好方法。

 

标签:number,decimal,小数点,js,丢失,小数,精度,math
来源: https://www.cnblogs.com/jdWu-d/p/15960242.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有