蓝桥杯算法:高精度加法
大整数加法:
问题描述
输入两个整数a和b,输出这两个整数的和。a和b都不超过100位。
算法描述
由于a和b都比较大,所以不能直接使用语言中的标准数据类型来存储。对于这种问题,一般使用数组来处理。
定义一个数组A,A[0]用于存储a的个位,A[1]用于存储a的十位,依此类推。同样可以用一个数组B来存储b。
计算c = a + b的时候,首先将A[0]与B[0]相加,如果有进位产生,则把进位(即和的十位数)存入r,把和的个位数存入C[0],即C[0]等于(A[0]+B[0])%10。然后计算A[1]与B[1]相加,这时还应将低位进上来的值r也加起来,即C[1]应该是A[1]、B[1]和r三个数的和.如果又有进位产生,则仍可将新的进位存入到r中,和的个位存到C[1]中。依此类推,即可求出C的所有位。
最后将C输出即可。
定义一个数组A,A[0]用于存储a的个位,A[1]用于存储a的十位,依此类推。同样可以用一个数组B来存储b。
计算c = a + b的时候,首先将A[0]与B[0]相加,如果有进位产生,则把进位(即和的十位数)存入r,把和的个位数存入C[0],即C[0]等于(A[0]+B[0])%10。然后计算A[1]与B[1]相加,这时还应将低位进上来的值r也加起来,即C[1]应该是A[1]、B[1]和r三个数的和.如果又有进位产生,则仍可将新的进位存入到r中,和的个位存到C[1]中。依此类推,即可求出C的所有位。
最后将C输出即可。
输入格式
输入包括两行,第一行为一个非负整数a,第二行为一个非负整数b。两个整数都不超过100位,两数的最高位都不是0。
输出格式
输出一行,表示a + b的值。
样例输入
20100122201001221234567890
2010012220100122
2010012220100122
样例输出
20100122203011233454668012
1 import java.util.Scanner; 2 3 public class Main { 4 public static void main(String agrs[]){ 5 Scanner sc = new Scanner(System.in); 6 String a = sc.next(); 7 String b = sc.next(); 8 Bigsum(a, b); 9 } 10 11 private static void Bigsum(String a,String b){ 12 int maxLength = a.length()>b.length()?a.length():b.length(); 13 int[] array1 = new int[maxLength+1]; 14 for(int i=0;i<a.length();i++){ 15 array1[i] = a.charAt(a.length()-1-i)-'0'; 16 } 17 int[] array2 = new int[maxLength+1]; 18 for(int i=0;i<b.length();i++){ 19 array2[i] = b.charAt(b.length()-1-i)-'0'; 20 } 21 int[] result = new int[maxLength+1]; 22 for(int i=0;i<result.length;i++){ 23 int temp = result[i]; 24 temp += array1[i]; 25 temp += array2[i]; 26 if(temp>=10){ 27 result[i+1] = temp/10; 28 result[i+1] = temp%10; 29 } 30 result[i] = temp; 31 } 32 33 StringBuffer sb = new StringBuffer(); 34 //是否找到大整数的最高有效位 35 boolean findFirst = false; 36 for(int i=result.length-1;i>=0;i--){ 37 if(!findFirst){ 38 if(result[i]==0){ 39 continue; 40 } 41 findFirst = true; 42 } 43 sb.append(result[i]); 44 } 45 System.out.println(sb.toString()); 46 } 47 48 }
其中判断得到的大整数的最高有效位还可以这样操作:
1 int book = 0; 2 for(int i=maxLength-1;i>=0;i--) { 3 if(result[i]>0) { 4 book = i; //找到大整数最高有效位不是0的位置 5 break; 6 } 7 8 } 9 for(int t=f;t>=0;t--) { 10 System.out.print(k[t]); 11 }
更简单的方法就是直接使用BigDecimal:
1 import java.math.BigDecimal; 2 import java.util.Scanner; 3 4 public class Main { 5 public static void main(String agrs[]){ 6 BigDecimal aBigDecimal; 7 BigDecimal bigDecimal; 8 BigDecimal cBigDecimal; 9 Scanner sc = new Scanner(System.in); 10 aBigDecimal = sc.nextBigDecimal(); 11 bigDecimal = sc.nextBigDecimal(); 12 cBigDecimal = aBigDecimal.add(bigDecimal); 13 System.out.println(cBigDecimal); 14 } 15 }
问:大数如果包含了小数部分,该如何处理呢?
答;比如 3.1415926 + 1314.9 ,可以都乘上10的7次方, 变成 31415926 + 13149000000, 得到的结果再除以10的7次方。
【优化】:原整数拆分到可以被直接计算就可以,int类型的取值范围是-2147483648 — 2147483648,最多有10位整数,为了防止溢出,可以把大整数的每9位作为数组的一个元素。(也可以按照long类型拆分)如将60位整数可以拆分为长度为7的数组,每个元素存储9位。
【注】:拆分的时候,每一个9位数内部不反转,但9位数之间可以反转。
大整数乘法:
分两步:首先将整数B的每一个数位和整数A依次相乘,得到中间结果。然后将所有中间结果相加,得到最终结果。
1 public static String multiply(String a,String b){ 2 int length1 = a.length(); 3 int length2 = b.length(); 4 int[] array1 = new int[length1]; 5 for(int i=0;i<length1;i++){ 6 array1[i] = a.charAt(length1-1-i)-'0'; 7 } 8 int[] array2 = new int[length2]; 9 for(int i=0;i<length2;i++){ 10 array2[i] = b.charAt(length2-1-i)-'0'; 11 } 12 13 int[] result = new int[length1+length2]; 14 for(int i=0;i<length2;i++){ 15 for(int j=0;j<length1;j++){ 16 result[i+j] += array2[i]*array1[j]; 17 if(result[i+j] >= 10){ 18 result[i+j+1] += result[i+j]/10; 19 result[i+j] = result[i+j]%10; 20 } 21 } 22 } 23 24 StringBuilder sb = new StringBuilder(); 25 boolean findFirst = false; 26 for(int i=result.length-1;i>=0;i--){ 27 if(!findFirst){ 28 if(result[i] == 0){ 29 continue; 30 } 31 findFirst = true; 32 } 33 sb.append(result[i]); 34 } 35 return sb.toString(); 36 }