字符串形式表示的大数据相乘

255 阅读3分钟
package pandy.a;

 import java.util.Scanner;
 public class Test1{
     public static void main(String[] args) {
         Scanner sc = new Scanner(System.in);
         String s = sc.nextLine();
         String[] arr = s.split("\\s+");//使用空格将数组分成两部分
         boolean flag=false;
         char [] ar1,ar2;
         
         if(arr[0].charAt(0)=='-' && arr[1].charAt(0)=='-'){
             /**
              * 将数组分成两部分 如果两部分之前都带有负号 那么直接从第一个位置进行切割
              * 将字符串转化为字符数组 ar1 是被空格分隔的转化为数组的第一项
              * ar2是转化成的字符数组的第二项
              */
              ar1 = arr[0].substring(1).toCharArray();
              ar2 = arr[1].substring(1).toCharArray();
         }
         /**
          * 如果第一部分有负号
          * 还是切割 但是设定为负的标志
          */
         else if(arr[0].charAt(0)=='-'){
             flag=true;
             ar1 = arr[0].substring(1).toCharArray();
             ar2 = arr[1].toCharArray();
         }
         /**
          * 如果数组的第二项之前有负号
          * 设定为负的标志
          */
         else if(arr[1].charAt(0)=='-'){
             flag=true;
             ar1 = arr[0].toCharArray();
             ar2 = arr[1].substring(1).toCharArray();
         }
         /**
          * 都是正数 直接转化成字符数组即可
          */
         else{
             ar1 = arr[0].toCharArray();
             ar2 = arr[1].toCharArray();
         }
         /**
          *大数运算要减去字节 0 因为其中存放的是sacii码 减去字节0  才能得到真正的数字
          */
         for(int i=0;i<ar1.length;i++){
             ar1[i]=(char) (ar1[i]-'0');
         }
         for(int i=0;i<ar2.length;i++){
             ar2[i]=(char) (ar2[i]-'0');
         }
         /**
          * 用于存储运算结果的新的数组 数组的长度为两子数组之和
          */
         int [] result=new int[ar1.length+ar2.length];
         /**
          *为了逻辑清晰 首先不解决进位问题 进位问题留在最后
          * 首先是每个位次分别相乘 存入相应的位置
          * 一个位次与另一个位次上面的数值相乘(不考虑进位问题) 所得的数值放在相乘之后
          * 忽略0之后 最高的那个位次所处的位置上
          * 例如 234*56
          * 6*4 在个位 6*3在十位 6*2在百位
          * 5*4 20个10 则arr[1] += 20; 表示20个10相乘
          * 其中数组的位数从低到高表示的是 进位
          */
         for(int i=ar2.length-1;i>-1;i--){
             for(int j=ar1.length-1;j>-1;j--){
                 result[ar1.length-1-j+ar2.length-1-i]=ar1[j]*ar2[i]+result[ar1.length-1-j+ar2.length-1-i];    
             }
         }
         /**
          * 处理进位问题
          * i表示的是进位 新的数组的位数 最大是以前两个子数组长度的和
          * 如果相应的位数大于0 则需要向上进位
          * 取临时变量 就是当前位数与10 的取余
          * 然后将对当前对10 的取余就是当前位数所显示的数字 比如
          * 19%10 = 9 当前arr[i] 的位置就是9 那个1 向前进位 然后进位之后arr[i+1] i+1还要加上对10的
          * 倍数的进位 进位如果能大于9  继续重复上面的步骤 直到在整个新数组中处理完所有的数值
          */
         for(int i=0;i<ar1.length+ar2.length;i++){
             if(result[i]>9){
                 int temp=result[i]/10;
                 result[i]=result[i]%10;
                 result[i+1]=result[i+1]+temp;
                 
             }
         }
         /**
          * 处理负号问题
          * 创建字符串的操作对象 此对象为线程不安全
          * 在标志位的位置加上负号 然后如果对应位相加为0
          * 记录相应的无效位数 此位数是从数组的最低位
          * 也就是所显示出来的数值的最高位进行计算
          */
         StringBuilder buffer=new StringBuilder();
         if(flag) buffer.append('-');
         int counter=0;
         if(result[ar1.length+ar2.length-1]==0) counter=1;
         for(int i=ar1.length+ar2.length-2;i>-1;i--){
             if(result[i+1]==0 && result[i]==0) counter++;
             else break;
         }
         /**
          * 最终的处理部分  最后的数值长度就是两者子长度减去无效位
          * 然后将各个数值全部归位 剔除无效位 避免占用数组空间
          * 之后将result[i]上的数字全部交给buffer接管
          */
         for(int i=ar1.length+ar2.length-counter-1;i>-1;i--){
             buffer.append(result[i]);
         }
         System.out.println(buffer.toString());
     }
 }