zoukankan      html  css  js  c++  java
  • js 计算精度问题

    一 浮点计算精读出现的问题枚举

    0.1 + 0.2               // 0.30000000000000004  not  0.3
    0.3 - 0.2             // 0.09999999999999998    not 0.1
    1.005 * 100         //100.49999999999999  not  100.5 , 所以用 Math.round(1.005*100)/100 得到的也是1 not  1.01
    0.69 / 10           // 0.06899999999999999  not 0.069
    1.005.toFixed(2)  // '1.00' not '1.01' (四舍五入:采用银行家算法 - 不准确)
    

    二 js 浮点计算 精度出现精读问题的原因

    js所有数字包括整数浮点数只有一种类型 - Number类型,它遵循IEEE 754标准,使用固定的64位固定长度来表示,也就是标准的double 双精度浮点数。(单精读 是float 32位) 。
    这样的存储结构优点是可以归一化处理整数和小数,节省存储空间。
      64位比特又可分为三个部分:

    符号位S:第 1 位是正负数符号位(sign),0代表正数,1代表负数

    指数位E:中间的 11 位存储指数(exponent),用来表示次方数

    尾数位M:最后的 52 位是尾数(mantissa),超出的部分自动进一舍零

    所以产生误差的原因:由于有一些浮点数用二进制表示时是无穷的,当浮点数转化为二进制进行存储时,会把超过53位之后的进行合并导致精读丢失。

    三 js 浮点运算解决方案 (保留多少位数小数,末尾实现四舍五入)

    方法一: 自定义函数
        function toFixed(n, d) {
          if (n > Number.MAX_SAFE_INTEGER || n < Number.MIN_SAFE_INTEGER) {
            throw new Error('超过js安全计算值范围,此函数暂不支持!');
          }
          const radix = 10 ** d;
          let num = math.floor(n * radix);
          const a = String(n).split('.');
          if (a[1] && a[1].length >= d) {
            if (Number(a[1][d]) >= 5) {
              num += 1;
            }
          }
          return num / radix;
        }
    
    方法二 利用mathjs 库
    import { create, all, round } from 'mathjs';
    
    const config = {
      number: 'BigNumber',
      precision: 64,
    };
    
    const mathJs = create(all, config);
    // number 和 bignumber类型
    // mathJs.evaluate('0.1 + 0.2');  // 0.3
    // 默认保留两位小数,实现四舍五入
    
    export const math = (expression, precision = 2) => {
      return round(mathJs.number(mathJs.evaluate(expression)), precision);
    };
    
    math('0.1 + 0.2'); // 0.3
    
  • 相关阅读:
    关于一个单机游戏发行的一些见解
    怎么租借电话号码
    NUMA架构的优缺点
    Windows 安装PostgreSQL
    Oracle查询当前用户下的所有表及sqlplus 设置 列宽
    Xshell调整终端显示的最大行数(缓冲区)
    PostgreSQL 索引膨胀
    Linux 清空缓存
    load多个数据文件的yaml
    Linux LVM逻辑卷配置过程详解(创建,增加,减少,删除,卸载)
  • 原文地址:https://www.cnblogs.com/honkerzh/p/14551197.html
Copyright © 2011-2022 走看看