两个大数相加

    今天在没事做算法题练习时,有道求a+b的题,本以为很简单,结果没想到提交了好几次都没通过,让自己折腾了好大半天才找出了各种坑,记录一下解题思路。

      题目如下:

      计算a+b的和
      每行包行两个整数a和b
      对于每行输入对应输出一行a和b的和
      输入
      1 5
      输出
      6

       一看到题,本能的觉得这坑太明显了吧,肯定是需要考虑数据溢出问题,不能想当然的默认输入为普通整型数据,要考虑到如果输入一个超出整型范围的数字时的情况,如”12345678987654321”和”98765432123456789”这样的两个数。

       解题思路是,将进行计算的两个数转换为字符数组,然后末尾对齐,逐一计算对应位置上位数的和,然后用第三个字符数组来存储计算的结果,最后将结果字符数组转换为整数字符串进行输出。用来存储结果的result长度多取一位,以免溢出,当两个数字长度不一致时,无需考虑这个点,result长度只需和num1和num2中较长的长度一致即可。


         结果就写了个方法处理,但是提交后竟然不通过:

private static String additionCalculation(String num1,String num2){
        char[] num1CharArr = num1.toCharArray();
        char[] num2CharArr = num2.toCharArray();
        int resultArrSize = Math.max(num1CharArr.length, num2CharArr.length);
        char[] resultArr = new char[resultArrSize + 1];
        for (int i = 0; i < resultArr.length; i++) {
            resultArr[i] = '0';
        }
        int end1Index = num1CharArr.length - 1;
        int end2Index = num2CharArr.length - 1;
        int endResultIndex = resultArr.length - 1;
        for (int i = 0; i < resultArrSize; i++) {
            int n1 =0,n2=0,n3=0;
            if(end1Index >= 0){
                n1 = Integer.parseInt(num1CharArr[end1Index] + "");
            }
            if(end2Index >= 0){
                n2 = Integer.parseInt(num2CharArr[end2Index] + "");
            }
            n3 = Integer.parseInt(resultArr[endResultIndex] + "");
            n3 = n3 + n1 + n2;
            char[] cArr = String.valueOf(n3).toCharArray();
            if(cArr.length == 2){
                resultArr[endResultIndex -1] = cArr[0];
                resultArr[endResultIndex] = cArr[1];
            }else if(cArr.length == 1){
                resultArr[endResultIndex] = cArr[0];
            }
            end1Index--;
            end2Index--;
            endResultIndex--;
        }
        String result = String.valueOf(resultArr);
        if(result.startsWith("0")){
            result = result.substring(1);
        }
        return result;
    }


然后上网看了下其他网友的正确解答,正确代码竟然是这样的:

import java.util.Scanner;
 
public class Main {
 
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner scan =new  Scanner(System.in);
        while(scan.hasNext())
        System.out.println(scan.nextInt() + scan.nextInt());
        scan.close();
    }
 
}

       才发现自己考虑多了,不用考虑大数相加,只是简单的int型数字相加而已,然后发现自己没考虑数字的符号,自己的方法只支持两个正整数相加,不支持负数相加。这时发现如果要考虑负数相加的情况,其实是要考虑大数的减法,然后自己又重新完善代码,写了个大数减法的方法。

    /**
     * @see 两个大数的减法操作,不考虑符号(num1 - num2)
     * @param num1 被减数
     * @param num2 减数
     * @return
     */
    private static String subtractionCalculation(String num1,String num2){
        char[] num1CharArr = num1.toCharArray();
        char[] num2CharArr = num2.toCharArray();
        int resultArrSize = num1CharArr.length;
        int[] resultArr = new int[resultArrSize];
        for (int i = 0; i < resultArr.length; i++) {
            resultArr[i] = '0';
        }
        int end1Index = num1CharArr.length - 1;
        int end2Index = num2CharArr.length - 1;
        int endResultIndex = resultArr.length - 1;
        for (int i = 0; i < resultArrSize; i++) {
            int n1 =0,n2=0,n3=0;
            if(end1Index >= 0){
                n1 = Integer.parseInt(num1CharArr[end1Index] + "");
            }
            if(end2Index >= 0){
                n2 = Integer.parseInt(num2CharArr[end2Index] + "");
            }
            if(n1 >= n2){   //不需要借高位1
                n3 = n1 - n2;
            }else{  //低位不够减,高位借1当10
                n3 = 10 + n1 - n2;
                num1CharArr[end1Index-1] = String.valueOf(num1CharArr[end1Index-1] - '1').charAt(0);
            }
            resultArr[endResultIndex] = n3;
            end1Index--;
            end2Index--;
            endResultIndex--;
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < resultArr.length; i++) {
            sb.append(resultArr[i]+"");
        }
        String result = sb.toString();
        if(result.startsWith("0")){
            result = result.substring(1);
        }
        return result;
    }

        然后考虑到两个数正负情况,需分别考虑各自符号,如果都为正,直接加和即可;如果一正一负,需要用绝对值大的减绝对值小的,符号跟绝对值大的一致;如果都为负,两数相加,符号为负。然后考虑各种输入是否正常,做了一些完善,最终整体代码为:

package com.biyao.algorithm.calculation;

import java.util.Scanner;

/**
 * Created by Administrator
 * Create Date: 下午3:30:53
 * Description:**
 * 计算a+b的和

        每行包行两个整数a和b
        对于每行输入对应输出一行a和b的和
        输入
        1 5
        输出
        6
 */
public class SumCalculation {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        while(scan.hasNext()){
           String num1 = scan.next();
           String num2 = scan.next();
           String result = sumCalculation(num1,num2);
           System.out.println(result);
        }
    }
    
    /**
     * @see 求两个数的和(包含符号)
     * @param num1
     * @param num2
     * @return
     */
    public static String sumCalculation(String num1,String num2){
        if(!isIntegerNum(num1) || !isIntegerNum(num2)){
            return "数字格式不对,请重新输入";
        }
        int num1Symbol = checkNumIsPositive(num1);
        int num2Symbol = checkNumIsPositive(num2);
        if(num1Symbol == -1 && num2Symbol == -1){   //两个数均为负数
            return "-" + additionCalculation(removeNumSymbol(num1),removeNumSymbol(num2));
        }else if((num1Symbol == -1 && num2Symbol == 1) || 
                (num1Symbol == 1 && num2Symbol == -1)){    //两个数一正一负
            num1 = removeNumSymbol(num1);
            num2 = removeNumSymbol(num2);
            int numCompare = numCompare(num1,num2);
            String result = "";
            if(numCompare == 1){    //num1 > num2 绝对值
                result = subtractionCalculation(num1,num2);
                return num1Symbol == 1 ? result : "-" + result;
            }else if(numCompare == 0){
                return "0";
            }else if(numCompare == -1){
                result = subtractionCalculation(num2,num1);
                return num2Symbol == 1 ? result : "-" + result;
            }
        }
        return additionCalculation(removeNumSymbol(num1),removeNumSymbol(num2));
    }
    
    /**
     * @see 求两个非负正数的和
     * @param num1
     * @param num2
     * @return
     */
    private static String additionCalculation(String num1,String num2){
        char[] num1CharArr = num1.toCharArray();
        char[] num2CharArr = num2.toCharArray();
        int resultArrSize = Math.max(num1CharArr.length, num2CharArr.length);
        char[] resultArr = new char[resultArrSize + 1];
        for (int i = 0; i < resultArr.length; i++) {
            resultArr[i] = '0';
        }
        int end1Index = num1CharArr.length - 1;
        int end2Index = num2CharArr.length - 1;
        int endResultIndex = resultArr.length - 1;
        for (int i = 0; i < resultArrSize; i++) {
            int n1 =0,n2=0,n3=0;
            if(end1Index >= 0){
                n1 = Integer.parseInt(num1CharArr[end1Index] + "");
            }
            if(end2Index >= 0){
                n2 = Integer.parseInt(num2CharArr[end2Index] + "");
            }
            n3 = Integer.parseInt(resultArr[endResultIndex] + "");
            n3 = n3 + n1 + n2;
            char[] cArr = String.valueOf(n3).toCharArray();
            if(cArr.length == 2){
                resultArr[endResultIndex -1] = cArr[0];
                resultArr[endResultIndex] = cArr[1];
            }else if(cArr.length == 1){
                resultArr[endResultIndex] = cArr[0];
            }
            end1Index--;
            end2Index--;
            endResultIndex--;
        }
        String result = String.valueOf(resultArr);
        if(result.startsWith("0")){
            result = result.substring(1);
        }
        return result;
    }
    
    /**
     * @see 除去数字符号
     * @param num
     * @return
     */
    private static String removeNumSymbol(String num){
        if(num.startsWith("+") || num.startsWith("-")){
            return num.substring(1);
        }
        return num;
    }
    
    /**
     * @see 判断num是否为数字格式的
     * @param num
     * @return
     */
    private static boolean isIntegerNum(String num){
        if(num == null || num.isEmpty()){
            return false;
        }
        if(num.startsWith("+") || num.startsWith("-")){
            return num.substring(1).matches("[0-9]+");
        }
        return num.matches("[0-9]+");
    }
    
    /**
     * @see 判断数字字符串正负性
     * @param num
     * @return 正数-1,0-0,负数--1
     */
    private static int checkNumIsPositive(String num){
        if(num.startsWith("-")){
            return -1;
        }else if(num.startsWith("+")){
            return 1;
        }else if(num.equals("0")){
            return 0;
        }
        return 1;
    }
    
    /**
     * @see 数字大小比较
     * @param num1 数字1
     * @param num2 数字2
     * @return num1>num2 返回1,num1=num2 返回0,num1<num2 返回-1
     */
    private static int numCompare(String num1,String num2){
        int length1 = num1.length();
        int length2 = num2.length();
        if(length1 > length2){
            return 1;
        }else if(length1 == length2){
            int res = num1.compareTo(num2);
            if(res < 0){
                return -1;
            }else if(res == 0){
                return 0;
            }else{
                return 1;
            }
        }else if(length1 < length2){
            return -1;
        }
        return 0;
    }
    
    /**
     * @see 两个大数的减法操作,不考虑符号(num1 - num2)
     * @param num1 被减数
     * @param num2 减数
     * @return
     */
    private static String subtractionCalculation(String num1,String num2){
        char[] num1CharArr = num1.toCharArray();
        char[] num2CharArr = num2.toCharArray();
        int resultArrSize = num1CharArr.length;
        int[] resultArr = new int[resultArrSize];
        for (int i = 0; i < resultArr.length; i++) {
            resultArr[i] = '0';
        }
        int end1Index = num1CharArr.length - 1;
        int end2Index = num2CharArr.length - 1;
        int endResultIndex = resultArr.length - 1;
        for (int i = 0; i < resultArrSize; i++) {
            int n1 =0,n2=0,n3=0;
            if(end1Index >= 0){
                n1 = Integer.parseInt(num1CharArr[end1Index] + "");
            }
            if(end2Index >= 0){
                n2 = Integer.parseInt(num2CharArr[end2Index] + "");
            }
            if(n1 >= n2){   //不需要借高位1
                n3 = n1 - n2;
            }else{  //低位不够减,高位借1当10
                n3 = 10 + n1 - n2;
                num1CharArr[end1Index-1] = String.valueOf(num1CharArr[end1Index-1] - '1').charAt(0);
            }
            resultArr[endResultIndex] = n3;
            end1Index--;
            end2Index--;
            endResultIndex--;
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < resultArr.length; i++) {
            sb.append(resultArr[i]+"");
        }
        String result = sb.toString();
        if(result.startsWith("0")){
            result = result.substring(1);
        }
        return result;
    }
    
}

        在这代码基础上,通过简单的修改,即可满足大数相减。还有就是,如果代码操作能力比较好,其实可以不用第三个数组来存储运算结果的,直接在原有的两个数组上操作即可,那种是最省空间的方式,后续有时间继续优化一下。



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值