JS `BigInt` 与 `Number` 类型的显式转换与混合运算规则

各位观众,欢迎来到今天的JavaScript“数值大冒险”讲座!我是你们今天的向导,皮皮虾。今天咱们不聊框架,不谈架构,就聊聊JavaScript里的两个“数字公民”:NumberBigInt。它们俩啊,就像一对性格迥异的兄弟,虽然都姓“数”,但脾气秉性可是大不相同。今天咱们就来扒一扒它们之间的爱恨情仇,看看怎么让它们和平共处,一起为我们的代码添砖加瓦。

第一幕:Number君的自白——“我可是老牌劲旅!”

Number,这位老牌劲旅,在JavaScript里可是根深蒂固。它能表示整数、小数、正数、负数,甚至还能表示Infinity(无穷大)和NaN(Not a Number,不是一个数字)。

let age = 25; // 整数
let price = 99.99; // 小数
let pi = Math.PI; // 圆周率
let infinity = Infinity; // 无穷大
let notANumber = NaN; // 不是一个数字

Number 的优点在于它的广泛性和兼容性。几乎所有的JavaScript操作都默认使用 Number。 但是,Number 也有它的局限性。 它使用IEEE 754双精度浮点数格式,这意味着它只能精确表示-2^532^53 之间的整数。一旦超出这个范围,就会出现精度丢失的问题。

console.log(9007199254740992); // 9007199254740992
console.log(9007199254740993); // 9007199254740992  咦?怎么一样了?

看到没?超过安全整数范围后,Number 就开始“睁眼说瞎话”了,明明是不同的数字,它却显示成一样的。 这就是精度丢失,在处理金融数据或者需要高精度计算的场景下,这可是要命的!

第二幕:BigInt君的登场——“我就是来解决问题的!”

为了解决 Number 的精度问题,ES2020 引入了 BigIntBigInt 是一种新的原始类型,它可以表示任意精度的整数。 换句话说,只要你的内存足够大,BigInt 就能表示你想表示的任何整数。

创建 BigInt 有两种方式:

  1. 在整数后面加上 n
  2. 使用 BigInt() 构造函数。
let bigNumber1 = 123456789012345678901234567890n; // 使用 n 后缀
let bigNumber2 = BigInt(123456789012345678901234567890); // 使用 BigInt() 构造函数
let bigNumber3 = BigInt("123456789012345678901234567890"); // 也可以使用字符串

现在,我们再来试试之前 Number 无法精确表示的数字:

console.log(BigInt(9007199254740993)); // 9007199254740993n  终于正确了!

BigInt 就像一位救星,解决了 Number 的精度问题。 但是,BigInt 也不是万能的。 它不能直接和 Number 进行混合运算,而且不支持一些 Number 支持的操作,比如 Math.random()

第三幕:兄弟间的隔阂——“我们不能直接混合!”

NumberBigInt 就像是生活在不同世界的兄弟,它们不能直接进行混合运算。 如果你尝试这样做,JavaScript会毫不客气地抛出一个 TypeError

let number = 10;
let bigInt = 20n;

// console.log(number + bigInt); // TypeError: Cannot mix BigInt and other types, use explicit conversions

JavaScript 告诉你:“不能混合 BigInt 和其他类型,请使用显式转换。” 这就引出了我们今天的重点:显式转换。

第四幕:握手言和——显式转换的艺术

要让 NumberBigInt 和平共处,我们需要使用显式转换。 显式转换就像是兄弟俩之间的翻译,把一种语言翻译成另一种语言,让他们能够互相理解。

  • Number 转 BigInt:

    可以使用 BigInt() 构造函数将 Number 转换为 BigInt。 但是,需要注意的是,如果 Number 不是一个整数,那么转换后的 BigInt 会舍弃小数部分。

    let number = 10.5;
    let bigInt = BigInt(number); // 10n  注意:小数部分被舍弃了
    console.log(bigInt);

    请务必小心,因为这可能会导致数据丢失。

  • BigInt 转 Number:

    可以使用 Number() 构造函数将 BigInt 转换为 Number。 但是,需要注意的是,如果 BigInt 的值超出了 Number 的安全整数范围,那么转换后的 Number 可能会失去精度。

    let bigInt = 9007199254740993n;
    let number = Number(bigInt); // 9007199254740992  精度丢失了!
    console.log(number);

    所以,在将 BigInt 转换为 Number 时,一定要谨慎,确保不会丢失精度。

第五幕:混合运算的正确姿势

有了显式转换,我们就可以让 NumberBigInt 进行混合运算了。 但是,我们需要记住一个原则: 先转换,再运算。

let number = 10;
let bigInt = 20n;

let result1 = Number(bigInt) + number; // 先将 bigInt 转换为 Number,再相加
console.log(result1); // 30

let result2 = bigInt + BigInt(number); // 先将 number 转换为 BigInt,再相加
console.log(result2); // 30n

选择哪种转换方式取决于你的具体需求。 如果你需要得到一个 Number 类型的结果,就将 BigInt 转换为 Number; 如果你需要得到一个 BigInt 类型的结果,就将 Number 转换为 BigInt

第六幕:运算符的注意事项

BigInt 支持大部分常用的运算符,例如 +-*/% 等。 但是,有一些运算符需要特别注意:

  • 除法 /

    BigInt 的除法会舍弃小数部分,只保留整数部分。 这与 Number 的除法不同。

    console.log(10n / 3n); // 3n  小数部分被舍弃了
    console.log(10 / 3); // 3.3333333333333335
  • 位运算符:

    BigInt 支持位运算符,例如 &|^~<<>> 等。 这些运算符可以用于进行位操作。

    console.log(10n & 3n); // 2n
    console.log(10n | 3n); // 11n
    console.log(10n ^ 3n); // 9n
    console.log(~10n); // -11n
    console.log(10n << 2n); // 40n
    console.log(10n >> 2n); // 2n
  • 比较运算符:

    BigInt 可以使用比较运算符,例如 ==!=><>=<= 等。 比较运算符可以用于比较 BigIntNumber 的大小。

    console.log(10n == 10); // true  注意:这里是 ==,不是 ===
    console.log(10n === BigInt(10)); // true
    console.log(10n > 5); // true
    console.log(10n < 15); // true

    需要注意的是,在使用 == 比较 BigIntNumber 时,JavaScript 会进行隐式类型转换。 为了避免意外的结果,建议使用 === 进行严格比较。

第七幕:实际应用场景

BigInt 在很多场景下都非常有用,尤其是在需要处理大整数或者高精度计算的场景下。 举几个例子:

  • 金融计算:

    在金融计算中,精度至关重要。 使用 BigInt 可以避免因精度丢失而导致的错误。

  • 密码学:

    在密码学中,经常需要处理非常大的整数。 使用 BigInt 可以轻松地处理这些大整数。

  • 科学计算:

    在科学计算中,也经常需要处理高精度的数值。 使用 BigInt 可以满足这些需求。

  • ID 生成:

    有些系统需要生成全局唯一的ID,可以使用 BigInt 来保证ID的唯一性,即使在高并发的情况下也不会出现重复。

第八幕:总结与建议

今天我们一起探索了 NumberBigInt 的特性、显式转换规则以及混合运算的注意事项。 让我们来总结一下:

  • Number 是JavaScript的老牌劲旅,但存在精度问题。
  • BigInt 是JavaScript的新秀,可以表示任意精度的整数。
  • NumberBigInt 不能直接进行混合运算,需要使用显式转换。
  • 在进行显式转换时,需要注意可能出现的精度丢失问题。
  • BigInt 在金融计算、密码学、科学计算等领域有广泛的应用。

最后,给大家一些建议:

  • 在选择使用 Number 还是 BigInt 时,要根据具体的应用场景来决定。 如果不需要高精度,可以使用 Number; 如果需要高精度,就必须使用 BigInt
  • 在进行混合运算时,一定要使用显式转换,避免出现 TypeError
  • 在将 BigInt 转换为 Number 时,要注意可能出现的精度丢失问题。

好了,今天的“数值大冒险”讲座就到这里。 希望大家通过今天的学习,能够更好地理解和使用 NumberBigInt,让它们在你的代码中发挥更大的作用! 感谢大家的观看,我们下次再见!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注