解決大數相加的方法有不少,網上很容易搜到,下面介紹兩種,一種是在網上抄的,一種是本身想的,我將他們都用函數式的方式重寫了一遍。javascript
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
的寫法。java
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);
使用累加器實現git
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); }
函數式重寫github
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...oop