各位朋友,晚上好!今天咱们来聊聊 JavaScript 中的 BigInt
,这玩意儿在加密货币和高精度计算领域可是个宝贝。别看名字挺唬人,其实用起来也没那么复杂,我尽量用大白话给大家讲明白。
一、 啥是 BigInt? 为什么要它?
首先,得说说 JavaScript 里的数字。以前,JavaScript 只能精确表示 -2^53 + 1
到 2^53 - 1
之间的整数,也就是 Number 类型的 Number.MAX_SAFE_INTEGER
和 Number.MIN_SAFE_INTEGER
。超过这个范围,精度就没法保证了,会出现一些奇奇怪怪的现象。不信?试试看:
console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991
console.log(Number.MAX_SAFE_INTEGER + 1); // 9007199254740992
console.log(Number.MAX_SAFE_INTEGER + 2); // 9007199254740992 <- 啥?
console.log(Number.MAX_SAFE_INTEGER + 3); // 9007199254740994
你看,加 2 之后居然和加 1 的结果一样了!这是因为 JavaScript 的 Number 类型是用双精度浮点数来表示的,超过安全范围就没法精确表示了。
这在很多场景下是不能接受的。比如:
- 加密货币: 加密货币的交易金额、账户余额,那都是动辄几十上百位的数字,精度稍微有点偏差,你的比特币可能就凭空消失了,这谁受得了?
- 高精度计算: 科学计算、金融计算,对精度要求非常高,差一点点结果就谬以千里。
- 大整数 ID: 一些系统用超长的整数作为 ID,Number 类型也hold不住。
所以,我们需要一种能够精确表示任意大小整数的类型,BigInt
就应运而生了。
二、 BigInt 怎么用?
BigInt
的用法也很简单,有两种方式:
-
在数字后面加
n
:const bigNumber = 12345678901234567890n; console.log(typeof bigNumber); // "bigint"
-
使用
BigInt()
函数:const bigNumber2 = BigInt(12345678901234567890); const bigNumber3 = BigInt("12345678901234567890"); // 从字符串转换 console.log(typeof bigNumber2); // "bigint" console.log(typeof bigNumber3); // "bigint"
注意,BigInt()
函数可以接受数字或者字符串作为参数,但是不能接受小数。
三、 BigInt 的运算
BigInt
支持大部分常用的算术运算符,比如 +
、-
、*
、/
、%
、**
。
const a = 12345678901234567890n;
const b = 9876543210987654321n;
console.log(a + b); // 13333333333333333311n
console.log(a * b); // 1219326311126352690219326311126352690n
console.log(a / b); // 1n (注意,结果是整数,会截断小数部分)
console.log(a % b); // 12345678901234567890n
console.log(a ** 2n); // 152415787532388367501905199875019052100n
重要的事情说三遍:
BigInt
只能和BigInt
运算!BigInt
只能和BigInt
运算!BigInt
只能和BigInt
运算!
不能直接和 Number 类型的值进行运算,否则会报错。
const a = 10n;
const b = 5;
// console.log(a + b); // TypeError: Cannot mix BigInt and other types, use explicit conversions
console.log(a + BigInt(b)); // 15n (需要先将 Number 转换成 BigInt)
console.log(Number(a) + b); // 15 (需要将 BigInt 转换成 Number,但可能丢失精度)
注意精度丢失的风险! 将 BigInt
转换成 Number
类型可能会丢失精度,所以要谨慎使用。 最好只在确定结果在 Number 的安全范围内时才进行转换。
四、 BigInt 在加密货币中的应用
加密货币,比如比特币、以太坊,交易金额、账户余额都是很大的整数,而且对精度要求极高。BigInt
刚好可以满足这个需求。
举个例子,假设我们要实现一个简单的比特币交易函数:
// 模拟账户余额
let aliceBalance = 10000000000000000000n; // 10 BTC (假设 1 BTC = 10^18 satoshi)
let bobBalance = 5000000000000000000n; // 5 BTC
function transfer(senderBalance, receiverBalance, amount) {
if (senderBalance < amount) {
console.log("余额不足!");
return [senderBalance, receiverBalance];
}
const newSenderBalance = senderBalance - amount;
const newReceiverBalance = receiverBalance + amount;
console.log(`交易成功!转账金额: ${amount}`);
console.log(`Alice 余额: ${newSenderBalance}`);
console.log(`Bob 余额: ${newReceiverBalance}`);
return [newSenderBalance, newReceiverBalance];
}
// Alice 转账 2 BTC 给 Bob
[aliceBalance, bobBalance] = transfer(aliceBalance, bobBalance, 2000000000000000000n); // 2 BTC
// Alice 转账 10 BTC 给 Bob
[aliceBalance, bobBalance] = transfer(aliceBalance, bobBalance, 10000000000000000000n); // 10 BTC
// Alice 转账 100 BTC 给 Bob
[aliceBalance, bobBalance] = transfer(aliceBalance, bobBalance, 100000000000000000000n); // 余额不足
在这个例子中,我们用 BigInt
来表示账户余额和交易金额,确保了计算的精度,避免了因精度问题导致的资金损失。
五、 BigInt 在高精度计算中的应用
除了加密货币,BigInt
在高精度计算领域也有广泛的应用。比如,计算阶乘、计算圆周率等等。
我们来写一个计算阶乘的函数:
function factorial(n) {
if (n === 0n) {
return 1n;
} else {
return n * factorial(n - 1n);
}
}
console.log(factorial(20n)); // 2432902008176640000n
console.log(factorial(50n)); // 30414093201713378043612608166064768844377641568960512000000000000n
如果用 Number 类型来计算 factorial(50)
,早就溢出了,结果会变成 Infinity
。
六、 BigInt 的一些坑
虽然 BigInt
很好用,但也有一些需要注意的地方:
-
性能问题:
BigInt
的运算速度比 Number 类型慢,因为它需要更多的内存和计算资源。所以在对性能要求很高的场景下,要慎重使用。 -
类型转换: 前面已经说过了,
BigInt
只能和BigInt
运算,需要进行类型转换。而且,将BigInt
转换成Number
类型可能会丢失精度。 -
不支持某些操作符:
BigInt
不支持一元加号操作符+
,因为会被认为是要将值转换为 Number 类型。const a = 10n; // console.log(+a); // TypeError: Cannot convert a BigInt value to a number
-
位运算符: 位运算符(如
|
、&
、^
、>>
、<<
)在BigInt
中使用时,会移除符号位。这在某些场景下可能会导致意想不到的结果。
七、 BigInt 的浏览器兼容性
BigInt
的浏览器兼容性还不是很好,需要注意。
浏览器 | 支持版本 |
---|---|
Chrome | 67+ |
Firefox | 68+ |
Safari | 12+ |
Edge | 79+ |
Node.js | 10.4+ |
如果要在老版本的浏览器中使用 BigInt
,可以使用一些 polyfill 库,比如 big-integer
。
八、 BigInt 的一些实用技巧
-
格式化 BigInt: 可以使用
toLocaleString()
方法来格式化BigInt
,使其更易读。const bigNumber = 12345678901234567890n; console.log(bigNumber.toLocaleString()); // "12,345,678,901,234,567,890"
-
比较 BigInt: 可以使用
>
、<
、>=
、<=
、===
、!==
等比较运算符来比较BigInt
的大小。const a = 10n; const b = 20n; console.log(a > b); // false console.log(a < b); // true console.log(a === 10n); // true
-
使用第三方库: 如果需要更高级的
BigInt
功能,可以使用一些第三方库,比如jsbi
、big.js
等。这些库提供了更多的 API 和更优的性能。
九、 总结
BigInt
是 JavaScript 中一个非常重要的特性,它解决了 Number 类型无法精确表示大整数的问题,为加密货币、高精度计算等领域提供了强大的支持。
虽然 BigInt
有一些需要注意的地方,但只要掌握了它的基本用法和注意事项,就能在实际开发中灵活运用,解决各种大整数计算问题。
希望今天的讲座对大家有所帮助! 谢谢大家!