1.题目:
实现两个大数的加法运算
2.题目分析:
题目很清晰就是让我们实现一个大数据的加法操作,这个操作需要忽略位数的影响,很显然我们使用java提供的基本数据类型与对应的包装类是不可能完成该操作的,所以需要其他的方法,这里使用栈来解决该问题,可以使用栈来解决该问题的核心就是:两个个字符串类型数据放入两个栈后,无论它门原始是多少位,初始状态栈顶所属的位数都是个位,同时将栈顶出栈后,栈顶又都是十位,依次类推,直到将其中一个栈为空时,他们对应的位数都是一致的。一个栈为空后,较长的栈剩余在栈中的元素则不需要再参与计算,因为剩余的都是高位,我们可以直接继续将他与刚刚计算出来的数据进行拼接即可。下面看下代码实现:
3.代码实现:
笔者使用的栈是自己实现的一个栈,需要的话可以从这里查看:链栈的实现
public class BigNumberAdd { public static void main(String[] args) throws Exception{ System.out.println(add("123456789123456779","123456789123456779123")); } /** * 将两个字符串数字存入到不同的栈中 * @param numberOne * @param numberTwo * @return * @throws Exception */ public static String add(String numberOne,String numberTwo) throws Exception{ if(StringUtil.isEmpty(numberOne)||StringUtil.isEmpty(numberTwo)) throw new Exception("输入内容不可为空"); IStack linkedStackOne = new LinkedStack(); IStack linkedStackTwo = new LinkedStack(); //将两个字符串类型数据放入到栈中 for(int i=0;i<numberOne.length();i++){ linkedStackOne.push(String.valueOf(numberOne.charAt(i))); } for(int i=0;i<numberTwo.length();i++){ linkedStackTwo.push(String.valueOf(numberTwo.charAt(i))); } //调用将两个栈中的数据进行相加,然后返回一个新的栈 StringBuilder stringBuilder; if(linkedStackOne.length()<=linkedStackTwo.length()){ //较小的先传入 stringBuilder = popStack(linkedStackOne,linkedStackTwo); }else{ //较小的先传入 stringBuilder = popStack(linkedStackTwo,linkedStackOne); } return stringBuilder.toString(); } /** * 将两个栈中的栈顶数据相加 * 栈顶数据他的数据位置一定是一致的,这是可以使用栈来解决该问题的关键 * @param statckOne * @param stackTwo * @return * @throws Exception */ public static StringBuilder popStack(IStack statckOne,IStack stackTwo) throws Exception{ IStack iStack = new LinkedStack(); //谁小遍历谁即可,大的最后加上 if(statckOne.length()<=stackTwo.length()){ //标注是否需要进位 Integer temp = 0; while(!statckOne.isEmpty()){ if(!StringUtil.isEmpty((String)statckOne.peek())){ //深度较浅的栈有值 Integer intOne = new Integer((String)statckOne.pop()); Integer intTwo = new Integer((String)stackTwo.pop()); Integer intThree = new Integer(intOne+intTwo+temp); if(intThree>9){ temp = 1; iStack.push(String.valueOf(intThree%10)); }else{ temp = 0; iStack.push(String.valueOf(intThree)); } } } //深度较浅的栈无值时,拼接较长的栈与新栈,这样就是相加后的数据 //判断statckOne栈顶的数据相加后是否进位 if(temp==1) if(!stackTwo.isEmpty()){ Integer intFour = new Integer((String)stackTwo.pop()); stackTwo.push(String.valueOf(intFour+1)); //拼接两个栈:stackTwo、iStack return apend(stackTwo,iStack); }else{ //说明两个栈相等,进位1直接放进最高位 iStack.push(String.valueOf(1)); return apend(null,iStack); } else return apend(stackTwo,iStack); }else{ //该部分与上面逻辑相同,无差别,只是将两个数组调换位置 return null; } } /** * 传入的两个栈计算完成后的两个栈。 * 将两个栈中的数据元素拼接成一个新的字符串 * @param stackOne * @param stackTwo * @return */ public static StringBuilder apend(IStack stackOne,IStack stackTwo) throws Exception{ StringBuilder stringBuilder = new StringBuilder(); //将stackOne 中剩余的元素加入到stackTwo中 while(null != stackOne && !stackOne.isEmpty()) stackTwo.push(stackOne.pop()); while(null != stackTwo && !stackTwo.isEmpty()) stringBuilder.append(stackTwo.pop()); return stringBuilder; } }
上面代码思路还算清晰,第一部分就是将两个字符串数据存入到两个栈中,第二部分则是将这两个栈中的栈顶元素进行计算后出栈,并判断进位的场景,第三部分则是计算完成后,需要对较长的栈与计算完后的栈进行一个数据的合并形成一个新的字符串。这样就完成了大数的求和运算。
4.测试结果:
先来一个较小的数相加的,输出结果如下:
再来看下计算机计算的结果,如下,我们可以发现并没有不同,计算正确。
再来测试一个较大的数据,笔者选择在12345678前面加上很多的1来测试,测试结果如下:
笔者输入的两个数都是相同的,所以可以看到计算的结果是没有问题的,其他场景笔者也测试了,这里就不展示了。
5.总结
大数求和,关键点就是怎么实现对应的位置数据可以相加,使用栈来存储,则完美解决了这个问题,每次栈顶的元素对应的位置都是相同的,其他场景的实现就不难了。