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

在编程语言中,数值总会有个边界,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 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值