• JS-Number数字类型详解


    一、前言

    与其他语言不同,在JS中不区分整数与浮点数,统一为浮点数。所有数字类型统一都是基于 IEEE 754 标准来实现;采用的是“双精度”格式(即 64 位二进制)。这也意味着在小数计算时,会发生精度误差的情况(这并不是js独有的,其他基于IEEE 754标准的都会有这样的问题)。

    二、属性方法

    2.1 定义数字类型

    JS中的数字常量一般用十进制表示。例如:

    const a = 42;
    const b = 42.3;
    
    • 1
    • 2

    数字前后的 0 可以省略:(不建议,请规范写法)

    const a = 0.42;
    const b = .42;
    const c = 42.0;
    const d = 42.;
    
    • 1
    • 2
    • 3
    • 4

    数字常量还可以用其他格式来表示,八进制和十六进制;如果前缀为 0,则 JavaScript 会把数值常量解释为八进制数,如果前缀为 0 和 “x”,则解释为十六进制数。例如:

    const a = 070;
    const b = 0xFF;
    
    • 1
    • 2

    2.2 特殊的数值

    2.2.1 最大值:Number.MAX_SAFE_INTEGER

    最大整数是 2^53 - 1,即 9007199254740991,在 ES6 中被定义为Number.MAX_SAFE_INTEGER。

    2.2.2 最小值:Number.MIN_SAFE_INTEGER

    最小整数是 -9007199254740991,在 ES6 中被定义为 Number.MIN_SAFE_INTEGER。

    2.2.3 无穷数

    在进行运算时,可能都遇到过编译错误或者运行时错误,例如“除以 0”。这个时候不会得到无穷数,正无穷Infinity(Number.POSITIVE_INFINITY)与负无穷-Infinity(Number.NEGATIVE_INFINITY)。

    2.2.4 不是数字的数字:NaN

    如果数学运算的操作数不是数字类型(或者无法解析为常规的十进制或十六进制数字),就无法返回一个有效的数字,这种情况下返回值为 NaN。可以通过Number.isNaN(值)判断。

    const a = 2 / "测试"; // NaN
    a == NaN; // false
    a === NaN; // false
    Number.isNaN(a); // true
    
    • 1
    • 2
    • 3
    • 4

    注意:在运算的时候要注意避免得到NaN,防止程序出现错误;

    2.2.5 零值

    JavaScript 有一个常规的 0(也叫作+0)和一个 -0。-0 除了可以用作常量以外,也可以是某些数学运算的返回值。

    const a = 0 / -2; // -0
    const b = 0 * -2; // -0
    //  但是规范定义的返回结果是这样
    a.toString(); // "0"
    a + ""; // "0"
    String( a ); // "0"
    // 但是-0字符串翻过来就是对的
    +"-0"; // -0
    Number( "-0" ); // -0
    JSON.parse( "-0" ); // -0
    // 0与-0比较都为true
    -0 == 0; // true
    -0 === 0; // true
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    注意:需要注意正负0的比较,使用-0场景例如动画帧的移动速度等。

    2.3 数字的方法

    1. toSting:以字符串返回数值
    2. toFixed:返回字符串值,它包含了指定位数小数的数字(会四舍五入)
    3. toPrecision: 返回字符串值,它包含了指定长度的数字
    const a = 22;
    a.toString(); // '22'
    a.toFixed(3); // '22.000'
    const b = 2.222;
    b.toPrecision(2); // '2.2'
    b.toPrecision(3); // '2.22'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2.4 变量转换为数字

    1. Number:将变量转换为数字
    2. parseInt:返回数字的整数部分
    3. parseFloat:返回一个浮点数
    Number('22.2'); // 22.2
    parseInt('22.2'); // 22
    parseFloat('22.2'); // 22.2
    Number('测试'); // NaN
    parseInt('测试'); // NaN
    parseFloat('测试'); // NaN
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    注意:上述三个方法转换时,如果转换失败会返回NaN,开发中要注意避免。

    三、实战示例

    3.1 浮点数计算出现精度缺失

    3.1.1 发现问题

    在日常项目中会遇到小数之间的算术运算,例如商品价格的计算、账户金额的统计;涉及的小数时有时候会出现精度误差计算结果不准确,导致客户反馈bug。

    示例:

    console.log(0.1 + 0.2); // 0.30000000000000004
    
    • 1
    3.1.2 问题原因

    我们在上面有介绍过在JS中所有数字都是以IEEE-754标准格式64位浮点数形式储存,1与1.0是相同的。因为有些小数以二进制表示位数是无穷的。JavaScript会把超出53位之后的二进制舍弃。所以并不是JS中才会出现,所有基于IEEE-754标准的浮点数计算都会有这样的问题。

    3.1.3 解决方案

    使用第三方类库

    如果在项目中多处都需要使用浮点数计算,这个时候就需要考虑引用第三方类库方法来进行小数点之间的计算。这里推荐第三方类库:

    1. Math.js
    2. decimal.js
    3. big.js

    简易封装

    如果只是单纯处理个别计算问题时,可以使用下面简易封装的简易加法运算。核心思路就是:计算小数点后最大有几位,转换成10的指数幂进行计算,最后还原。

    /**
     * 精度相加
     */
    const addTogether = (n1, n2) => {
      let res1 = n1.toString().split(".")[1]
        ? n1.toString().split(".")[1].length
        : n1.toString().split(".")[0].length;
      let res2 = n2.toString().split(".")[1]
        ? n2.toString().split(".")[1].length
        : n2.toString().split(".")[0].length;
      let pow = Math.max(res1, res2);
      let base = Math.pow(10, pow);
      return (n1 * base + n2 * base) / base;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    3.2 计算出现NaN

    3.2.1 发现问题

    在项目中设计到表单输入时,有时候会进行两个变量之间的计算,有时候展示结果会出现NaN的情况。

    3.2.2 问题原因

    在进行算术运算时,会将变量类型隐式转换为数字类型;如果转换原类型不是字符串的数字时无法转换为数字,就会返回NaN

    3.2.3 解决方案

    涉及到表单问题时要设置输入框为number类型,在计算之前需要提前转换为Number类型,如果转换为NAN要及时报错或者根据业务需求兼容处理。

    const num = "测试";
    const curNum = Number.isNaN(Number(num)) ? 0 : Number(num);
    
    • 1
    • 2
  • 相关阅读:
    Javascript中改变函数内部this指向的方法:call()、apply()、bind()
    Linux系统Redis安装教程-附带后台启动
    2022华数杯华数杯A题 B题 C题 思路、程序
    ERP软件定价策略与模型设计
    LightDB中的存储过程(三)
    分组聚合不再难:Pandas groupby使用指南
    VK1620温控仪/智能电表LED数显驱动芯片3/4线接口内置 RC振荡器,提供技术支持
    前后端分离权限系统
    IOTDB的TsFile底层设计
    (六)RabbitMQ第二种模型:工作模型(Work Queues)
  • 原文地址:https://blog.csdn.net/IO14122/article/details/134438493