加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

两个函数式解决大数相加的方法

发布时间:2020-12-14 04:49:40 所属栏目:大数据 来源:网络整理
导读:解决大数相加的方法有很多,网上很容易搜到,下面介绍两种,一种是在网上抄的,一种是自己想的,我将他们都用函数式的方式重写了一遍。 这种是在网上抄的,的确非常简洁 function add(a,b) { let res='',c=0; a = a.split(''); b = b.split(''); while (a.le

解决大数相加的方法有很多,网上很容易搜到,下面介绍两种,一种是在网上抄的,一种是自己想的,我将他们都用函数式的方式重写了一遍。

这种是在网上抄的,的确非常简洁

function add(a,b) {
  let res='',c=0;
  a = a.split('');
  b = b.split('');
  while (a.length || b.length || c){
    c += ~~a.pop() + ~~b.pop();
    res = c % 10 + res;
    c = c>9;
  }
  return res.replace(/^0+/,'');
}

函数式重写,重点在尾递归,这是在函数式编程中代替while的写法。

let compose = (f,g) => (...args) => f(g(...args));
let addUnit = a => b => b + a;
let myPop = a => a.pop();  // 有副作用
let myNumber = a => ~~a;
let remainderTen = x => x % 10;
let isGreeterNine = x => x > 9;
let replaceHeadZero = x => x.replace(/^0+/,"");
let pAndN = compose(myNumber,myPop);
let loop = (a,b,res,c) => {    //尾递归,即在函数末尾自调用
  if (!a.length && !b.length && !c) return res;
  let getC = compose(addUnit(pAndN(b)),addUnit(pAndN(a)));
  let getEes = compose(addUnit(res),remainderTen);
  return loop(a,getEes(getC(c)),isGreeterNine(getC(c)));
}
let add = (a,b) => compose(replaceHeadZero,loop)(a.split(""),b.split(""),"",0);

自己想的

使用累加器实现

function add(a,b) {
  a = a.split('').reverse();
  b = b.split('').reverse();
  function addMap(aArrayIns,bArrayIns) {
    return aArrayIns.reduce((accumulator,currentValue,index) => {
      let c = ~~bArrayIns[index] + ~~currentValue + ~~accumulator[index];
      if (c >= 10) {
        accumulator[index] = (c - 10).toString();
        accumulator.push('1');
      } else {
        accumulator[index] = c.toString();
      }
      return accumulator;
    },[]).reverse().join('');
  }
  return a.length >= b.length ? addMap(a,b) : addMap(b,a);
}

函数式重写

let compose = (f,g) => x => f(g(x));
let myReverse = x => {
  let [...y] = x;
  return y.reverse();
};
let mySplit = x => x.split("");
let myToString = x => x.toString();
let myPushOne = x => {
  let [...y] = x;
  y.push("1");
  return y;
}
let setValue = index => value => targetArray => {
  let [...y] = targetArray;
  y[index] = value;
  return y;
}
let splitAndReverse = compose(myReverse,mySplit);
let myReduce = x => y => y.reduce(fnHandleAdd(splitAndReverse(x)),[]);
let fnHandleAdd = a => (accumulator,index) => {
  let c = ~~a[index] + ~~currentValue + ~~accumulator[index];
  return c >= 10
    ? compose(myPushOne,setValue(index)(myToString(c - 10)))(accumulator)
    : setValue(index)(myToString(c))(accumulator);
};

let addMap = (a,b) => compose(compose(R.join(""),myReverse),compose(myReduce(b),splitAndReverse))(a);
let add = (a,b) => a.length >= b.length ? addMap(a,a);

下面这种写法,很不优雅

let addMap = (a,splitAndReverse))(a);

最好compose可以实现组合任意个函数,效果如下

let addMap = (a,b) => compose(R.join(""),myReverse,myReduce(b),splitAndReverse)(a);

实现思路在:https://github.com/zhuanyongx...

我在github https://github.com/zhuanyongx...

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读