您的位置:首页 > 其它

两个大数相加

2017-04-30 20:02 288 查看
    今天在没事做算法题练习时,有道求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(!isI
4000
ntegerNum(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;
}

}

        在这代码基础上,通过简单的修改,即可满足大数相减。还有就是,如果代码操作能力比较好,其实可以不用第三个数组来存储运算结果的,直接在原有的两个数组上操作即可,那种是最省空间的方式,后续有时间继续优化一下。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息