解决大数相加的方法有很多,网上很容易搜到,下面介绍两种,一种是在网上抄的,一种是自己想的,我将他们都用函数式的方式重写了一遍。
这种是在网上抄的,的确非常简洁
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, b, 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, currentValue, 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, b) : addMap(b, a);
下面这种写法,很不优雅
let addMap = (a, b) => compose(compose(R.join(""), myReverse), compose(myReduce(b), splitAndReverse))(a);
最好compose可以实现组合任意个函数,效果如下
let addMap = (a, b) => compose(R.join(""), myReverse, myReduce(b), splitAndReverse)(a);
实现思路在:https://github.com/zhuanyongx...
我在github https://github.com/zhuanyongx...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。