资讯专栏INFORMATION COLUMN

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

AlanKeene / 3515人阅读

摘要:有副作用尾递归,即在函数末尾自调用自己想的使用累加器实现函数式重写下面这种写法,很不优雅最好可以实现组合任意个函数,效果如下实现思路在我在

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

这种是在网上抄的,的确非常简洁
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...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/95301.html

相关文章

  • 【前端来刷LeetCode】两数之和与两数相加

    摘要:给定表,存在函数,对任意给定的关键字值,代入函数后若能得到包含该关键字的记录在表中的地址,则称表为哈希表,函数为哈希函数。而中的对象就是基于哈希表结构,所以我们构造一个对象即可,是当前遍历到的值,是其与目标值的差。 大部分玩前端的小伙伴,在算法上都相对要薄弱些,毕竟调样式、调兼容就够掉头发的了,哪还有多余的头发再去折腾。 确实在前端中需要使用到算法的地方是比较少,但若要往高级方向发展,...

    BLUE 评论0 收藏0
  • 前端集成测试(一)- 认识nodeassert模块

    摘要:类的一个子类,表明断言的失败。可用于测试回调函数的参数。使用比较法测试参数与参数是否不全等。等待的完成,如果是一个函数,则立即调用该函数并等待返回的完成,然后检查是否被。 FEAT FrontEnd Automates Test 前端全自动化测试 序章 文章开头先引一个知乎上的问答:如何进行前端自动化测试? 我相信做过前端的朋友都有这个疑问。希望这篇文章里你能看到一些别人的测试方法,帮...

    Jinkey 评论0 收藏0
  • [Leetcode] Multiply String and Big Interger 大数乘法加法

    摘要:因为被乘数每一位数字和乘数相乘的结果是依次错开的,所以就没问题。判断两个数的大小的方法,是先判断其长度,如果长度不一样,则较长的较大,如果长度一样,则需要比较每一位。 Multiply Strings Given two numbers represented as strings, return multiplication of the numbers as a string. ...

    keithxiaoy 评论0 收藏0
  • LeetCode13 - Roman to Integer

    摘要:解题思路罗马数字是符号和加操作的一个组合。他基于以下七个符号。组合规则基本数字中的任何一个,自身连用构成数目,或者放在大数的右边连用构成数目,都不能超过三个放在大数的左边只能用一个。想更一进步的支持我,请扫描下方的二维码,你懂的 Given a roman numeral, convert it to an integer. Input is guaranteed to be...

    elisa.yang 评论0 收藏0
  • ​前端教学讲义:JS基础

    讲义内容:JS 诞生的背景、基本类型、运算符 以下内容只涉及 ES5 标准,ES6 增加的新内容可以在网上查找到。 JS 诞生的背景 上世纪 90 年代网景公司开发的浏览器独步天下 一个叫做 Brendan Eich 的工程师受命于开发一款脚本语言,来增强浏览器的功能。 这名工程师花费了 10 天时间设计出了第一个版本,名叫 LiveScript。 后来因为当时 Java 正红,公司将其改名为 J...

    walterrwu 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<