zoukankan      html  css  js  c++  java
  • JS bigint 数据类型的学习

    BigInt 可能会成为自 ES2015 引入 Symbol 之后,增加的第一个新的内置类型。并且 BigInt 类型在 TypeScript3.2 版本被内置。。。本篇将简单记录下BigInt

    js的第七种基本数据类型BigInt

    js 采用双精度浮点数,这也导致了精度有限的问题。在 js 中,Number 基本类型可以精确表示的最大整数是 2^53。因此早期会有这如下的“bug”:

    let max = Number.MAX_SAFE_INTEGER;    // 最大安全整数
    
    let max1 = max + 1
    let max2 = max + 2
    
    max1 === max2 //true

    为了解决这个限制,BigInt出现在了ECMAScript标准中。

    let max = BigInt(Number.MAX_SAFE_INTEGER);
    
    let max1 = max + 1n
    let max2 = max + 2n
    
    max1 === max2 // false

    介绍

    BigInt 可以表示任意大的整数。

    创建

    语法:

    BigInt(value);

    其中参数:

      value: 创建对象的数值。可以是字符串或者整数。

    注意, BigInt() 不是构造函数,因此不能使用 new 操作符。

    除了通过BigInt构造函数,我们还可以通过在一个整数字面量后面加 n 的方式定义一个 BigInt ,如:10n

    例:

    let valA = 10n;
    let valB = BigInt(10);
    
    console.log(valA === valB);     // true

    类型判断

    我们可以通过typeof操作符来判断是否为BigInt类型(返回字符串"bigint"),如

    typeof 1n === 'bigint'; // true
    typeof BigInt('1') === 'bigint'; // true

    同样的,我们也可以用最通用的Object.prototype.toString方法(返回字符串"[object BigInt]"

    Object.prototype.toString.call(10n) === '[object BigInt]';    // true

    运算

    以下操作符可以和 BigInt 一起使用: +*-**% 。除 >>> (无符号右移)之外的 位操作 也可以支持。(因为 BigInt 都是有符号的 >>> (无符号右移)不能用于 BigInt)。

    为了兼容 asm.js ,.BigInt 不支持单目 (+) 运算符。

    const previousMaxSafe = BigInt(Number.MAX_SAFE_INTEGER);
    // 9007199254740991n
    
    const maxPlusOne = previousMaxSafe + 1n;
    // 9007199254740992n
     
    const theFuture = previousMaxSafe + 2n;
    // 9007199254740993n, this works now!
    
    const multi = previousMaxSafe * 2n;
    // 18014398509481982n
    
    const subtr = multi – 10n;
    // 18014398509481972n
    
    const mod = multi % 10n;
    // 2n
    
    const bigN = 2n ** 54n;
    // 18014398509481984n
    
    bigN * -1n
    // –18014398509481984n

    当使用 BigInt 时,带小数的运算会被取整。

    const expected = 4n / 2n;
    // 2n
    
    const rounded = 5n / 2n;
    // 2n, not 2.5n

    方法

    BigInt.asIntN()

    将 BigInt 值转换为一个 -2^width - 1 与 2^(width-1) - 1 之间的有符号整数。

    语法:

    BigInt.asIntN(width, bigint);

    如:

    const max = 2n ** 64n - 1n;
    
    BigInt.asUintN(64, max);
    // 18446744073709551615n
    
    BigInt.asUintN(64, max + 1n);
    // 0n
    // zero because of overflow

    BigInt.asUintN()

    将一个 BigInt 值转换为 0 与 2^width-1 之间的无符号整数。

    语法:

    BigInt.asUintN(width, bigint);
    const max = 2n ** 64n - 1n;
    
    BigInt.asUintN(64, max);
    // 18446744073709551615n
    
    BigInt.asUintN(64, max + 1n);
    // 0n
    // zero because of overflow

    BigInt和Number

    BigInt 和 Number 不是严格相等的,但是宽松相等的。

    10n === 10
    // false
    
    10n == 10
    // true

    Number 和 BigInt 可以进行比较。

    1n < 2;        // true
    
    2n > 1;        // true
    
    2 > 2;        // false
    
    2n > 2;        // false
    
    2n >= 2;    // true

    两者也可以混在一个数组内并排序。

    const mixed = [4n, 6, -12n, 10, 4, 0, 0n];    // [4n, 6, -12n, 10, 4, 0, 0n]
    
    mixed.sort();    // [-12n, 0, 0n, 10, 4n, 4, 6]

    BigInt 在需要转换成 Boolean 的时表现跟 Number 类似:如通过 Boolean 函数转换;用于 Logical Operators ||, &&, 和 ! 的操作数;或者用于在像 if statement 这样的条件语句中。

    它在某些方面类似于 Number ,但是也有几个关键的不同点:不能用与 Math 对象中的方法;不能和任何 Number 实例混合运算,两者必须转换成同一种类型。在两种类型来回转换时要小心,因为 BigInt 变量在转换成 Number 变量时可能会丢失精度。

    不允许隐式类型转换

    因为隐式类型转换可能丢失信息,所以不允许在bigint和 Number 之间进行混合操作。当混合使用大整数和浮点数时,结果值可能无法由BigInt或Number精确表示。

    如:

    10n + 1;    // Uncaught TypeError: Cannot mix BigInt and other types, use explicit conversions
    Math.max(2n, 4n, 6n);    // TypeError...

    BigInt和String

    难免会遇到数字和字符串的转换,BigInt也不例外,不过可惜的是BigInt转为String时,其标志性的n会被省略,如

    String(10n);    // '10'
    '' + 11n;    // '11'

    因此也导致以下情况:

    // array
    let arr = [1, 2, 3, 4, 5];
    
    arr[2] === arr[2n];    // true
    
    // object
    let obj = {
        '1': '1',
        '2': '2',
        '3': '3',
        '4': '4'
    };
    
    obj['1'] === obj[1n];        // true

    零值

    BigInt 没有 Number 的正零(+0)和负零(-0)之分。因为 BigInt 表示的是整数

    无穷和NaN判断

    很有趣的现象

    isFinite(10n);    // Uncaught TypeError: Cannot convert a BigInt value to a number
    Number.isFinite(10n);    // false
    
    isNaN(10n);    // Uncaught TypeError: Cannot convert a BigInt value to a number
    Number.isNaN(10n);    // false

    由此我们可以看出isFinite()和Number.isFinite()、isNaN()和Number.isNaN()的区别:isFinite(val)/isNaN(val)的工作机制都是讲参数值val转为数值后再进行比较判断,而Number.isFinite(val)/Number.isNaN(val)则可以理解为直接简单粗暴的变量全等判断(val === Infinity/val === NaN

    兼容

    如图,兼容情况并不是很好。并且转换BigInt是一个极其复杂的过程,这会导致严重的运行时性能损失。直接polyfill BigInt也是不可能的,因为该提议改变了几个现有操作符的行为。目前,更好的选择是使用JSBI库,它是BigInt提案的纯JS实现,访问地址>>

    使用如下:

    import JSBI from './jsbi.mjs';
    
    const max = JSBI.BigInt(Number.MAX_SAFE_INTEGER);
    console.log(String(max));
    // → '9007199254740991'
    const other = JSBI.BigInt('2');
    const result = JSBI.add(max, other);
    console.log(String(result));
    // → '9007199254740993'

    TypeScript

    BigInt 类型在 TypeScript3.2 版本被内置,

    在TypeScript中,BigInt 和 Number 都是有表示数字的意思,但是实际上两者类型是不同的:

    declare let valA: number;
    declare let valB: bigint;
    
    valA = valB; // error: Type 'bigint' is not assignable to type 'number'.
    valB = valA; // error: Type 'number' is not assignable to type 'bigint'.

    除了类型定义,TypeScript 中 BigInt 其他使用方法同 ES。

  • 相关阅读:
    Android客户端与服务器交互方式-小结
    个人工作总结01
    第7周学习进度
    第6周学习进度
    PHP_D4_“简易聊天室 ”的具体技术实现
    php_D3_“简易聊天室 ”实现的关键技术 详解
    团队介绍
    最大联通子数组
    构建之法阅读笔记04
    大道至简阅读笔记04
  • 原文地址:https://www.cnblogs.com/MrZhujl/p/13746232.html
Copyright © 2011-2022 走看看