当前位置: 代码迷 >> 综合 >> 老生常谈:如何进行大整数相加?扩展知识细节
  详细解决方案

老生常谈:如何进行大整数相加?扩展知识细节

热度:58   发布时间:2024-01-15 17:57:52.0

在编程语言中,数值总会有个边界,JavaScript 也不例外,我们通过下面的代码可以看到边界:

Number.MAX_VALUE   // 1.7976931348623157e+308
Number.MIN_VALUE   // 5e-324
Number.MAX_SAFE_INTEGER  //9007199254740991
Number.MIN_SAFE_INTEGER  //-9007199254740991

然而,如果要对超大的数值进行相加,就不能依靠传统的 +了,因为超过 Number.MAX_SAFE_INTEGER 就会被转换成科学计数,并不是我们想要看到的直观的结果。接下来,我们设计个算法来实现这个加法。

算法思路

  1. 设计两个入参: a 和 b, 它们的类型可能是: string | Number。设计一个返回结果 result。
  2. 将参数按照字符串的方式,逐字符拆分,从个位(最右边开始),一位一位的相加,如 大于10 则进位。
  3. 将逐位相加的结果与 result 进行相加,最后得到字符串结果。

这个是大致思路,里面包含了一些细节,接下来通过代码来实现。

代码实现

方案一:比较直观,没有太多代码技巧,但是表达出了思路,面试的话估计可以得个 60分

function bigNumber(a, b) {
    // 转成字符串后再计算长度let i = a.toString().length;let j = b.toString().length;let result = "";let carry = 0; // 进位标识,1 进位// 从a和b的个位起逐个相加while (i > 0 || j > 0) {
    let x = y = sum = 0;if (i != 0) {
    x = parseInt(a[i - 1]);i--;}if (j != 0) {
    y = parseInt(b[j - 1]);j--;}sum = x + y + carry;// 操过10则进位if (sum >= 10) {
    carry = 1;sum -= 10;} else {
    carry = 0;}// 字符串的形式相加result = sum + result;}if (carry) {
    result = carry + result;}return result;
};

方案二: 运用了语言的技巧,代码量较少,可扩展的知识点较多。面试的话估计可以得 90分

function bigNumber(a, b) {
    // 将字符串转换成数组let x = a.toString().split("");let y = b.toString().split("");let carry = 0; // 进位标识,1 进位let result = "";// 从a和b的个位起逐个相加while (x.length || y.length) {
    // ~~x.pop()每次取出数组的最后一个,也就是个位开始let sum = ~~x.pop() + ~~y.pop() + carry;carry = sum >= 10 ? 1 : 0; result = (sum % 10) + result; // 取余再和result相加}if (carry) {
    result = carry + result;}return result;
};

扩展知识点: ~~运算符

从上面的代码可以看出,最让人费解的就是 ~~ 运算符。它其实是可以将一些变量转成 Number 类型,适用场景如下:

  • 数字类型的字符串可以转换为纯数字:
let a = '999';
~~a; // 999 
  • 字符串中带了字母、符号或者其他除数字外的,一律转化成 Number 类型的 0
let a = 'abc001';
~~a; // 0 
  • 布尔类型,如果为true则输出1,false则输出0
let a = true;
~~a; // 1 
  • 遇到结果是 undefined 的输出 0
let a = undefined;
~~a; // 0