在日常开发中,我们经常需要处理大数值。然而在 JavaScript 中,Number 类型的精度是有限的,当处理超过 Number.MAX_SAFE_INTEGER (2^53-1)的数值时,会出现精度丢失的情况。为了解决这个问题,ES2021 引入了一个新的数据类型:bigint。
bigint 类型的定义
bigint 类型是一种新的基本数据类型,用来表示任意精度的整数。它的取值范围是 -2^53+1 到 2^53-1,超出这个范围的整数可以被表示为一个字符串或者数组。
bigint 类型的字面量表示
bigint 类型的字面量表示是一个整数后面加上 n,例如:
const num1 = 1234567890123456789012345678901234567890n;
const num2 = BigInt('1234567890123456789012345678901234567890');bigint 类型的操作
bigint 类型可以进行所有的基本数学运算,包括加、减、乘、除、取模等。例如:
const num1 = 1234567890123456789012345678901234567890n; const num2 = 9876543210987654321098765432109876543210n; console.log(num1 + num2); // 11111111111111111111111111111111111111100n console.log(num1 - num2); // -8641975320864197532098765432108641975310n console.log(num1 * num2); // 12193263113702179516544333036606428168813555354823835097121261047540798765400n console.log(num1 / num2); // 0n console.log(num1 % num2); // 1234567890123456789012345678901234567890n
bigint 类型的转换
bigint 类型可以和 Number 类型相互转换,但需要注意精度的问题。如果 bigint 的值超出了 Number.MAX_SAFE_INTEGER 的范围,转换成 Number 类型时会出现精度丢失的问题。例如:
const num1 = 1234567890123456789012345678901234567890n; const num2 = BigInt(Number.MAX_SAFE_INTEGER); console.log(Number(num1)); // Uncaught RangeError: bigint out of range console.log(Number(num2)); // 9007199254740991 console.log(num2 + 1n); // 9007199254740992n console.log(num2 + 2n); // Uncaught RangeError: bigint out of range
bigint 类型的应用
bigint 类型在实际开发中有很多应用场景,例如处理加密算法中的大数值、处理金融数据中的精确计算等。
实现斐波那契数列
我们可以使用 bigint 类型来实现斐波那契数列中的大数值计算。例如:
// www.javascriptcn.com code example
function fibonacci(n) {
let a = 0n, b = 1n;
for (let i = 0; i < n; i++) {
[a, b] = [b, a + b];
}
return a;
}
console.log(fibonacci(100)); // 354224848179261915075n实现高精度计算器
我们可以使用 bigint 类型来实现一个高精度计算器,支持大数值的加、减、乘、除、取模等操作。例如:
// www.javascriptcn.com code example
class Calculator {
add(a, b) {
let carry = 0n, res = '';
while (a.length || b.length || carry) {
const x = Number(a.pop() || 0);
const y = Number(b.pop() || 0);
const sum = BigInt(x + y + carry);
res = String(sum % 10n) + res;
carry = sum / 10n;
}
return res;
}
subtract(a, b) {
let borrow = 0n, res = '';
while (a.length || b.length) {
const x = Number(a.pop() || 0);
const y = Number(b.pop() || 0);
const diff = BigInt(x - y - borrow);
res = String((diff + 10n) % 10n) + res;
borrow = diff < 0n ? 1n : 0n;
}
return res;
}
multiply(a, b) {
const len1 = a.length, len2 = b.length;
const res = Array(len1 + len2).fill(0n);
for (let i = len1 - 1; i >= 0; i--) {
for (let j = len2 - 1; j >= 0; j--) {
const mul = BigInt(a[i]) * BigInt(b[j]);
const p1 = i + j, p2 = i + j + 1;
const sum = mul + res[p2];
res[p2] = sum % 10n;
res[p1] += sum / 10n;
}
}
while (res.length && res[0] === 0n) {
res.shift();
}
return res.length ? res.join('') : '0';
}
divide(a, b) {
const len1 = a.length, len2 = b.length;
if (len1 < len2 || (len1 === len2 && a < b)) {
return '0';
}
let res = '', r = '';
for (let i = 0; i < len1; i++) {
r += a[i];
let cnt = 0;
while (r >= b) {
r -= b;
cnt++;
}
res += cnt;
}
return res.replace(/^0+/, '') || '0';
}
mod(a, b) {
const len1 = a.length, len2 = b.length;
if (len1 < len2 || (len1 === len2 && a < b)) {
return a;
}
let r = '';
for (let i = 0; i < len1; i++) {
r += a[i];
while (r >= b) {
r -= b;
}
}
return r;
}
}
const calculator = new Calculator();
console.log(calculator.add('12345678901234567890', '98765432109876543210')); // 111111111111111111100
console.log(calculator.subtract('12345678901234567890', '98765432109876543210')); // -86419753208641975320
console.log(calculator.multiply('12345678901234567890', '98765432109876543210')); // 12193263113702179516544333036606428168813555354823835097121261047540798765400
console.log(calculator.divide('12345678901234567890', '98765432109876543210')); // 0
console.log(calculator.mod('12345678901234567890', '98765432109876543210')); // 12345678901234567890小结
bigint 类型是 ES2021 中引入的一个新的基本数据类型,用来表示任意精度的整数。它可以进行所有基本的数学运算,并且可以和 Number 类型相互转换。在实际开发中,bigint 类型可以用来处理大数值的计算,例如实现斐波那契数列、高精度计算器等。我们需要注意 bigint 类型和 Number 类型之间的精度问题,避免出现精度丢失的情况。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67da39a1a941bf7134204f00