13、大整数操作

long型数据最大能对21亿以内的数字操作,可是如果两个100亿的数字相加,或者相乘呢?long型肯定不能满足需求。如果是用在天文学的计算,数字更可能达到几十位,甚至是几百位的数字。这已经不可能再使用系统定义的数据类型了,那该怎么解决?

主要思想:
不管是大整数相加,还是大整数相乘,都可以把一个数字的各位数字存进一个数组里面,然后再对数组进行操作。就像小学时候的列竖式做加法或者乘法一样。

大数相加

/******* 
a和b存放要相加的两个数的逆序,c将存放逆序的和,l为两个加数位数的最大值。 
例如320+427:a={0,2,3},b={7,2,4},l=3,计算结果c={7,4,7}。 
*******/  
int Adding(int a[],int b[],int c[],int l)  
{  
    int i,t;  
    for(i=0;i<l;i++)  
    {  
        t=a[i]+b[i]+c[i];  
        c[i]=t%10;  
        c[i+1]=t/10;///////////进位  
    }  
    if(c[i]!=0)  
        return i+1;  
    return i;///////////////////函数返回数组c的长度  
}  

大数相乘

/*a和b存放要相乘的两个数的逆序,c将存放逆序的积,la、lb分别为两个乘数的位数。  
例如315*66:a={5,1,3},b={6,6},la=3,lb=2,计算结果c={0,9,7,0,2}。  
*******/   
int Multiply(int a[],int b[],int c[],int la,int lb)  
{  
    int i,j,t;  
    for(i=0;i<lb;i++)  
        for(j=0;j<la;j++)  
        {  
            t=a[j]*b[i]+c[i+j];  
            c[i+j]=t%10;  
            c[i+j+1]+=t/10;////////////进位  
        }  
    if(c[la+lb-1]!=0)  
        return la+lb;  
    return la+lb-1;////////////////////函数返回乘积的位数  
}

参考:https://blog.csdn.net/u012027907/article/details/12191465

/** 
 * @计算超大整型 
 */  
public class LargeInteger {  

    String FirstNumStr;   //第一个数的字符串  

    LargeInteger(String var){  //构造方法(给第一个数字符串赋值)  
        this.FirstNumStr = var;  
    }  
    /** 
     * 加方法 
     * @param SecondNumStr 被加数 
     * @return 相加的结果 
     */  
    public String add(String SecondNumStr){ //加方法  

        int LengthA = FirstNumStr.length(); //求出第一个数字符串长度  
        int LengthB = SecondNumStr.length();//求出第二个数字符串长度  

        boolean IsMinus = false; //是否带负号  
        if((FirstNumStr.charAt(0) == '-') && (SecondNumStr.charAt(0) == '-')){//都带负号  
            IsMinus = !IsMinus;  
        }else if(FirstNumStr.charAt(0) == '-'){ //第一个数带负号  
            FirstNumStr = FirstNumStr.substring(1);  
            String second = FirstNumStr;  
            FirstNumStr = SecondNumStr;  
            return  subtract(second);  
        }else if(SecondNumStr.charAt(0) == '-'){ //第二个数带负号  
            SecondNumStr = SecondNumStr.substring(1);  
            return subtract(SecondNumStr);  
        }  

        int MaxLength = LengthA >= LengthB?LengthA:LengthB; //求出最大的长度  
        MaxLength += 1; //加1是为了给可能的进位留出一位  

        int []FirstNum = new int[MaxLength];  //定义第一个数整型数组  
        int []SecondNum = new int[MaxLength]; //定义第二个数整型数组  

        int []Result = new int[MaxLength];    //定义存放结果数组  
        int MidResult = 0;  //中间结果  
        int num = 0;    //记录将字符转为整型的数  
        for(int i = LengthA-1,j = MaxLength-1; i >= 0; i--,j--){ //将第一个数字符串转为整型数组  
            switch(FirstNumStr.charAt(i)){  
            case '0':num = 0;break;  
            case '1':num = 1;break;  
            case '2':num = 2;break;  
            case '3':num = 3;break;  
            case '4':num = 4;break;  
            case '5':num = 5;break;  
            case '6':num = 6;break;  
            case '7':num = 7;break;  
            case '8':num = 8;break;  
            case '9':num = 9;break;  
            default:num = 0;break;  
            }  
            FirstNum[j] = num;  
        }  
        num = 0;  
        for(int i = LengthB-1,j = MaxLength-1; i >= 0; i--,j--){//将第二个数字符串转为整型数组  
            switch(SecondNumStr.charAt(i)){  
            case '0':num = 0;break;  
            case '1':num = 1;break;  
            case '2':num = 2;break;  
            case '3':num = 3;break;  
            case '4':num = 4;break;  
            case '5':num = 5;break;  
            case '6':num = 6;break;  
            case '7':num = 7;break;  
            case '8':num = 8;break;  
            case '9':num = 9;break;  
            default:num = 0;break;  
            }  
            SecondNum[j] = num;  
        }  


        for(int i = MaxLength-1; i >= 0; i--){       //从个位开始加  
            MidResult = FirstNum[i] + SecondNum[i];  //记录两数相加的中间结果  
            if(MidResult >= 10){    //进位  
                Result[i] = MidResult % 10;  //本位的数  
                FirstNum[i-1] = FirstNum[i-1] + 1; //进位  
            }else{  
                Result[i] = MidResult; //没有进位直接赋值  
            }  
        }  

        String ResultStr = "";  
        if(IsMinus){        //  
            ResultStr = "-";  
        }  

        boolean flag = false;  
        for(int j = 0 ; j < MaxLength; j++){ //将整型数组转为字符串  
            if(Result[j] != 0){ //数组前面有0不赋值给字符串           
                flag = true;  
            }  
            if(flag){  
                ResultStr += Result[j];  
            }  
        }  

        return ResultStr;  
    }  
    /** 
     * 减方法 
     * @param SecondNumStr 
     * @return 相减的结果 
     */  
    public String subtract(String SecondNumStr){  

        int LengthA = FirstNumStr.length(); //求出第一个数字符串长度  
        int LengthB = SecondNumStr.length();//求出第二个数字符串长度  

        if((FirstNumStr.charAt(0) == '-') && (SecondNumStr.charAt(0) == '-')){  
            String second = FirstNumStr;  
            FirstNumStr = SecondNumStr.substring(1);  
            return add(second);  

        }else if(FirstNumStr.charAt(0) == '-'){  
            SecondNumStr = "-"+SecondNumStr;  
            return  add(SecondNumStr);  
        }else if(SecondNumStr.charAt(0) == '-'){  
            SecondNumStr = SecondNumStr.substring(1);  
            return add(SecondNumStr);  
        }  

        int MaxLength = LengthA >= LengthB?LengthA:LengthB; //求出最大的长度  

        int []FirstNum = new int[MaxLength];  //定义第一个数整型数组  
        int []SecondNum = new int[MaxLength]; //定义第二个数整型数组  

        int []Result = new int[MaxLength];    //定义存放结果数组  
        int MidResult = 0;  //中间结果  
        int num = 0;    //记录将字符转为整型的数  
        for(int i = LengthA-1,j = MaxLength-1; i >= 0; i--,j--){ //将第一个数字符串转为整型数组  
            switch(FirstNumStr.charAt(i)){  
            case '0':num = 0;break;  
            case '1':num = 1;break;  
            case '2':num = 2;break;  
            case '3':num = 3;break;  
            case '4':num = 4;break;  
            case '5':num = 5;break;  
            case '6':num = 6;break;  
            case '7':num = 7;break;  
            case '8':num = 8;break;  
            case '9':num = 9;break;  
            default:num = 0;break;  
            }  
            FirstNum[j] = num;  
        }  
        num = 0;  
        for(int i = LengthB-1,j = MaxLength-1; i >= 0; i--,j--){//将第二个数字符串转为整型数组  
            switch(SecondNumStr.charAt(i)){  
            case '0':num = 0;break;  
            case '1':num = 1;break;  
            case '2':num = 2;break;  
            case '3':num = 3;break;  
            case '4':num = 4;break;  
            case '5':num = 5;break;  
            case '6':num = 6;break;  
            case '7':num = 7;break;  
            case '8':num = 8;break;  
            case '9':num = 9;break;  
            default:num = 0;break;  
            }  
            SecondNum[j] = num;  
        }  

        boolean FirstNumLarger = false;  
Breakflag:for(int i = 0; i <MaxLength; i++){  //判断第一个数是否大于第二个数  
            if(FirstNum[i] > SecondNum[i]){  
                FirstNumLarger = true;  
                break Breakflag;  
            }else if(FirstNum[i] == SecondNum[i]){  
                continue;  
            }else{  
                break Breakflag;  
            }  
        }  

        for(int i = MaxLength-1; i >= 0; i--){       //从个位开始加  
            if(FirstNumLarger){ //大数减小数  
                MidResult = FirstNum[i] - SecondNum[i];  //记录两数相减的中间结果                
            }else{  
                MidResult = SecondNum[i] - FirstNum[i];  
            }  
            if(MidResult < 0){    //借位  
                Result[i] = 10 + MidResult ;  //本位的数  
                if(FirstNumLarger){  
                    FirstNum[i-1] = FirstNum[i-1] - 1; //借位  
                }else{  
                    SecondNum[i-1] = SecondNum[i-1] - 1;  
                }  

            }else{  
                Result[i] = MidResult; //没有进位直接赋值  
            }  
        }  

        String ResultStr = "";  
        if(!FirstNumLarger){  
            ResultStr = "-";  
        }  
        boolean flag = false;  
        for(int j = 0 ; j < MaxLength; j++){ //将整型数组转为字符串  
            if(Result[j] != 0){ //数组前面有0不赋值给字符串           
                flag = true;  
            }  
            if(flag){  
                ResultStr += Result[j];  
            }  
        }  
        if(ResultStr == "-"){ //相减为0时,赋值0  
            ResultStr = "0";  
        }  
        return ResultStr;  
    }  
    /** 
     * 乘方法 
     * @param SecondNumStr 
     * @return 相乘的结果 
     */  
    public String multiply(String SecondNumStr){  

        boolean IsMinus = false; //是否带负号  
        if(FirstNumStr.charAt(0) == '-'){  
            IsMinus = !IsMinus;  
            FirstNumStr = FirstNumStr.substring(1);  
        }  
        if(SecondNumStr.charAt(0) == '-'){  
            IsMinus = !IsMinus;  
            SecondNumStr = SecondNumStr.substring(1);  
        }  
        int LengthA = FirstNumStr.length(); //求出第一个数字符串长度  
        int LengthB = SecondNumStr.length();//求出第二个数字符串长度  

        int MaxLength = LengthA >= LengthB?LengthA:LengthB; //求出最大的长度  
        MaxLength++; //多预留一个空间  
        int ResultLength = MaxLength*2; //两个数相乘最多为两个数中最大长度的2倍  

        int []FirstNum = new int[MaxLength];  //定义第一个数整型数组  
        int []SecondNum = new int[MaxLength]; //定义第二个数整型数组  
        int []TempNum = new int[MaxLength];   //临时整型数组存储中间计算结果  

        int []Result = new int[ResultLength];    //定义存放结果数组  
        int MidResult = 0;  //中间结果  
        int num = 0;    //记录将字符转为整型的数  

        for(int i = LengthA-1,j = MaxLength-1; i >= 0; i--,j--){ //将第一个数字符串转为整型数组  
            switch(FirstNumStr.charAt(i)){  
            case '0':num = 0;break;  
            case '1':num = 1;break;  
            case '2':num = 2;break;  
            case '3':num = 3;break;  
            case '4':num = 4;break;  
            case '5':num = 5;break;  
            case '6':num = 6;break;  
            case '7':num = 7;break;  
            case '8':num = 8;break;  
            case '9':num = 9;break;  
            default:num = 0;break;  
            }  
            FirstNum[j] = num;  
        }  
        num = 0;  
        for(int i = LengthB-1,j = MaxLength-1; i >= 0; i--,j--){//将第二个数字符串转为整型数组  
            switch(SecondNumStr.charAt(i)){  
            case '0':num = 0;break;  
            case '1':num = 1;break;  
            case '2':num = 2;break;  
            case '3':num = 3;break;  
            case '4':num = 4;break;  
            case '5':num = 5;break;  
            case '6':num = 6;break;  
            case '7':num = 7;break;  
            case '8':num = 8;break;  
            case '9':num = 9;break;  
            default:num = 0;break;  
            }  
            SecondNum[j] = num;  
        }  
        int PriorNum = 0; //进位  
        int k = ResultLength - 1; //Result[k]从个位向前赋值  

        for(int i = MaxLength-1; i > 0; i--){      //控制第二个数的个、十、百向前推移  
            for(int j = MaxLength-1; j > 0; j--){  //使第二个数与第一个数的每一位相乘  
                MidResult = SecondNum[i]*FirstNum[j]; //保存两个数相乘的中间结果  
                PriorNum = MidResult / 10;  //进位数  
            //  if(MidResult >= 10){    //乘的结果需要进位  
                    TempNum[j] += MidResult % 10; //本位的值  
                    if(TempNum[j] >= 10){    //如果本位的值仍需进位,则再进一位  
                        TempNum[j] = TempNum[j] % 10; //本位的最终值  
                        PriorNum++; //需要的进位数再加一  
                    }  
                    TempNum[j-1] = TempNum[j-1]+PriorNum; //进位  
            //  }  
            }  
            int m = k;  
            for(int n = MaxLength-1; n >= 0; n--,m--){  //将临时存储的数组复制给最终结果数组  
                Result[m] += TempNum[n]; //赋值  
                if(Result[m] >= 10){  //若赋值相加需要进位,则进位  
                    Result[m-1] += Result[m]/10; //先进位  
                    Result[m] = Result[m] % 10;  //后算本位的值(这两句代码不能颠倒)      
                }  
                TempNum[n] = 0; //临时数组置0,以便下一个循环用  
            }  
            k--;//下一次临时数组赋值时徐翔高位移一位  
        }  
        String ResultStr = "";  
        if(IsMinus){  
            ResultStr = "-";  
        }  

        boolean flag = false;  
        for(int j = 0 ; j < ResultLength; j++){ //将整型数组转为字符串  
            if(Result[j] != 0){ //数组前面有0不赋值给字符串           
                flag = true;  
            }  
            if(flag){  
                ResultStr += Result[j];  
            }  
        }  
        if(ResultStr == ""){ //相乘为0时,显示0  
            ResultStr = "0";  
        }  
        return ResultStr;  
    }  
    /** 
     * 除方法 
     * @param SecondNumStr 
     * @return 除的结果 
     */  
    public String divide(String SecondNumStr){  

        boolean IsMinus = false; //是否带负号  
        if(FirstNumStr.charAt(0) == '-'){    //第一个数带了负号  
            IsMinus = !IsMinus;  
            FirstNumStr = FirstNumStr.substring(1);           
        }  
        if(SecondNumStr.charAt(0) == '-'){ //第二个数带了负号  
            IsMinus = !IsMinus;  
            SecondNumStr = SecondNumStr.substring(1);             
        }  
        int LengthA = FirstNumStr.length(); //求出第一个数字符串长度  
        int LengthB = SecondNumStr.length();//求出第二个数字符串长度  

        if(LengthA < LengthB){   //因为是整除,所以第一个数小与第二个数时,直接返回 0  
            return "0";  
        }else if(LengthA == LengthB){ //字符串相等  
            String result = subtract(SecondNumStr);   
            if(result.charAt(0) == '-'){ //第一个数小,直接返回0  
                return "0";  
            }else if(result.charAt(0) == '0'){ //两个数相等,则返回1  
                return "1";  
            }  
        }  

        int []Result =  new int[LengthA]; //存放最终结果的整型数组  

        String SubTemp = ""; //存放字串  
        String Temp = "";  
        String result = "";  
        String StoreFirstNumStr = FirstNumStr;//临时存放第一个数  

        for(int i = LengthB-1 ; i < LengthA; i++ ){  
            if(i == LengthB-1){  
                SubTemp = FirstNumStr.substring(0,LengthB);  
            }else{  
                FirstNumStr = SubTemp;  
                SubTemp = subtract(Temp)+StoreFirstNumStr.substring(i,i+1);  
            }  
            for(int j = 9; j >= 0 ;j--){ //每一位的商值从9-0挨个试  

                FirstNumStr = Integer.toString(j); //将整型转为字符串  
                Temp = multiply(SecondNumStr);     //9-0中的数与被除数相乘  

                FirstNumStr = SubTemp;  
                result = subtract(Temp);//计算差值  

                if(result.charAt(0) == '-'){ //若差值为负,则继续  
                    continue;  
                }else{                      //否则,确定商,并跳出循环  
                    Result[i] = j;  
                    break;  
                }  
            }  
        }  
         String ResultStr = "";//最终返回值的字符串  
            if(IsMinus){      //计算结果为负  
                ResultStr = "-";  
            }  

        boolean flag = false;  //标记变量,标记从Result[0]-Reslult[n-1]哪一位开始不为0,才赋值给ResultStr  
        for(int j = 0 ; j < LengthA; j++){ //将整型数组转为字符串  
            if(Result[j] != 0){ //数组前面有0不赋值给字符串           
                flag = true;  
            }  
            if(flag){  
                ResultStr += Result[j];  
            }  
        }  
        if(ResultStr == ""){ //相乘为0时,显示0  
            ResultStr = "0";  
        }  

        return ResultStr;  
    }  

} 

测试:

public class Basic {  

    /** 
     * @param args 
     */  
    public static void main(String[] args) {  
        // TODO Auto-generated method stub  
                  //测试代码  
        LargeInteger One = new LargeInteger("1024546448494645445444464545454545456546546548897454644");  
        String Two = "1024546448494645454654";  

        String result1 = One.add(Two);  
        String result2 = One.subtract(Two);  
        String result3 = One.multiply(Two);  
        String result4 = One.divide(Two);  

        BigInteger one = new BigInteger("1024546448494645445444464545454545456546546548897454644");  

        BigInteger Result1 = one.add(new BigInteger("1024546448494645454654"));  
        BigInteger Result2 = one.subtract(new BigInteger("1024546448494645454654"));  
        BigInteger Result3 = one.multiply(new BigInteger("1024546448494645454654"));  
        BigInteger Result4 = one.divide(new BigInteger("1024546448494645454654"));  

        System.out.println(""+result1+"\n"+Result1+"\n\n");  
        System.out.println(""+result2+"\n"+Result2+"\n\n");  
        System.out.println(""+result3+"\n"+Result3+"\n\n");  
        System.out.println(""+result4+"\n"+Result4+"\n\n");  
    }  

} 
阅读更多

没有更多推荐了,返回首页