java 进行超大整数的加减乘除四则运算,自己部分实现BigInteger

问题分析:

加减运算:

两数进行加减,都可以转为两个基本运算:

  • 两个非负数相加--------------- plusAdd()
 1 private  StringBuffer plusAdd(String strNum1,String strNum2){
 2         //把两个数字字符串倒置,并存入字符数组
 3         char [] num1 = new StringBuffer(strNum1).reverse().toString().toCharArray();
 4         char [] num2 = new StringBuffer(strNum2).reverse().toString().toCharArray();
 5         int maxLength = Math.max(num1.length,num2.length);
 6         int minLength = Math.min(num1.length,num2.length);
 7         //n位和m位的非负整数相加的和,要么是max(n,m)位,要么是max(n,m)+1位。
 8         StringBuffer value = new StringBuffer();
 9     
10         /*--------------计算和数开始------------------------*/
11         int i,jinWei=0;
12         for(i=0;i<minLength;i++){
13             int temp = jinWei + num1[i] - '0'  +num2[i] - '0';
14             value.append((char)(temp%10 + '0')); 
15             jinWei = temp/10;
16         }
17         if(maxLength == num1.length)
18             jinWei = oneBitAdd(jinWei,num1,i,maxLength,value);
19         else
20             jinWei = oneBitAdd(jinWei,num2,i,maxLength,value);
21         if(jinWei != 0)
22              value.append((char)(jinWei +'0'));
23         /*--------------计算和数结束------------------------*/
24         return deleteZero(value).reverse();
25     }
  • 一个较大的非负数减去一个不大于前一个数的非负数 ----- plusMinus()
 1 private  StringBuffer plusMinus(String bigNumStr,String smallNumStr){
 2         //把两个数字字符串倒置,并存入字符数组
 3         char [] num1 = new StringBuffer(bigNumStr).reverse().toString().toCharArray();
 4         char [] num2 = new StringBuffer(smallNumStr).reverse().toString().toCharArray();
 5         StringBuffer value = new StringBuffer();
 6         
 7         /*--------------计算减法开始------------------------*/    
 8         int i,temp,jieWei = 0;
 9         for(i = 0;i<smallNumStr.length();i++){
10             temp = num1[i]  - jieWei - num2[i];
11             jieWei = oneBitMinus(temp,value,i);    
12         }
13         //处理较大数比较小数多出来的位
14         for(;i<bigNumStr.length();i++){
15             temp = num1[i] - '0' - jieWei;
16             jieWei = oneBitMinus(temp,value,i);
17         }
18         /*--------------计算减法结束------------------------*/
19         return deleteZero(value).reverse();
20     }

假设num1 , num2 分别为被加数 、加数,则最终结果只可能是以下情况:

  1. num1 非负数 num2 非负数
  2. num1 负数 num2 负数 、
  3. num1 非负数 num2 负数
  4. num1 负数 num2 非负数

上面四种情况可以转为:

  1. plusAdd(num1,num2)
  2. - plusAdd(- num1,- num2)
  3. plusMinus(num1,- num2)
  4. plusMinus(num2,- num2)

减法类似。

乘法运算:

乘法也可以转化为一个基本运算: 两个正整数相乘----plusMulti()

private  StringBuffer plusMulti(StringBuffer str1,StringBuffer str2) {
        //新建两个StringBuffer,存储两数的前后倒置。
        StringBuffer num1 = new StringBuffer(str1.substring(0)).reverse();
        StringBuffer num2 = new StringBuffer(str2.substring(0)).reverse();
        StringBuffer array = new StringBuffer();
        //n位数和m位数相乘,得到的结果的位数只能是n+m或者n+m-1。
        int len = str1.length() + str2.length();
        for(int i = 0;i<len-1;i++){
            array.append('0');
        }
        //标志n+m位
        array.append('+'); 
        
        //模拟竖式计算    
        for(int i = 0,j,jinWei = 0 ; i < str2.length() ; i++){
            jinWei = 0; //进位归位
            for(j = 0 ; j < str1.length() ; j++){
                int temp = (num2.charAt(i)-'0')*(num1.charAt(j)-'0') + jinWei + array.charAt(i+j) - '0';
                array.setCharAt(i+j,(char)(temp%10 + '0'));
                jinWei = temp /10;
            }
            if(jinWei !=0)
                array.setCharAt(i+j, (char)(jinWei +'0'));
        }
        if(array.charAt(len -1) == '+')
            array.setLength(len-1);
        return  array.reverse();
    }

各种情况只和plusMulti()有正负号的区别。其中一个数为0时,直接返回0即可。     

除法运算:

模拟手算除法的过程。

除法也可以转化为一个基本运算,两个非负数相除,除数不为0。-------------plusDivide()

 1 private StringBuffer plusDivide(String str1,String str2){  //str1  /   str2
 2         StringBuffer division = new StringBuffer();
 3         StringBuffer remain   = new StringBuffer();
 4         
 5         int end = 0;
 6         boolean  flag = false;            //标志在不够除时,是否需要上0。
 7         while(end < str1.length()){
 8             remain.append(str1.charAt(end));    //从被除数那里取一位
 9             if(Str1ThanStr2(remain.toString(),str2)){//能整除
10                 flag = true;
11                 int fullNum = Greatst(remain,str2);
12                 StringBuffer fullNumStr2 = plusMulti(new StringBuffer(str2),new StringBuffer(""+fullNum));
13                 division.append(""+fullNum);
14                 remain = plusMinus(remain.toString(),fullNumStr2.toString());
15             }
16             else if(flag)//不够除,补0
17                 division.append("0");
18             if(remain.toString().equals("0"))
19                 remain.setLength(0);
20             end++;
21         }
22         if(division.length() == 0){
23             return division.append('0');
24         }
25         return division;
26     }

各种情况至于plusDivide()只有符号的区别,除数为0时,特别处理下即可。

代码简介:

对外开放了四个方法:加减乘除。

  • public MyBigInteger Minus(MyBigInteger t) 减法
  • public MyBigInteger Multi(MyBigInteger t) 乘法
  • public MyBigInteger Add(MyBigInteger str) 加法
  • public MyBigInteger Divide(MyBigInteger t) 除法

测试:

乘法:进行10000!的运算,与用BigInteger类得到的结果一样。四种情况都测试了,结果一致。至少一个数为0时,也得到了了0。值得信赖!

其他的三种,测试没有乘法详细,如果有bug欢迎指出。

下面的main函数中,提供了

(175 + 231 - 143)*(-1978654)/(-54)

完整代码如下:

  1  
  2 public class MyBigInteger {
  3     private StringBuffer data;
  4     
  5     
  6     public MyBigInteger(){
  7         data = new StringBuffer("0");
  8     }
  9     public MyBigInteger(String str){
 10         data = new StringBuffer(str);
 11     }
 12     public MyBigInteger(StringBuffer str){
 13         data = new StringBuffer(str);
 14     }
 15  
 16     public int length(){
 17         return data.length();
 18     }
 19     public String toString(){
 20         return data.toString();
 21     }
 22     
 23     public boolean equals(Object obj){
 24         return data == ((MyBigInteger)obj).data;
 25     }
 26     
 27     /**
 28      * 功能:进行两个非负整数的相加
 29      */
 30     private  StringBuffer plusAdd(String strNum1,String strNum2){
 31         //把两个数字字符串倒置,并存入字符数组
 32         char [] num1 = new StringBuffer(strNum1).reverse().toString().toCharArray();
 33         char [] num2 = new StringBuffer(strNum2).reverse().toString().toCharArray();
 34         int maxLength = Math.max(num1.length,num2.length);
 35         int minLength = Math.min(num1.length,num2.length);
 36         //n位和m位的非负整数相加的和,要么是max(n,m)位,要么是max(n,m)+1位。
 37         StringBuffer value = new StringBuffer();
 38     
 39         /*--------------计算和数开始------------------------*/
 40         int i,jinWei=0;
 41         for(i=0;i<minLength;i++){
 42             int temp = jinWei + num1[i] - '0'  +num2[i] - '0';
 43             value.append((char)(temp%10 + '0')); 
 44             jinWei = temp/10;
 45         }
 46         if(maxLength == num1.length)
 47             jinWei = oneBitAdd(jinWei,num1,i,maxLength,value);
 48         else
 49             jinWei = oneBitAdd(jinWei,num2,i,maxLength,value);
 50         if(jinWei != 0)
 51              value.append((char)(jinWei +'0'));
 52         /*--------------计算和数结束------------------------*/
 53         return deleteZero(value).reverse();
 54     }
 55     /**
 56      * 进位加上字符数组一部分
 57      * @return
 58      */
 59     private int oneBitAdd(int jinWei,char []array,int beginIndex,int endIndex,StringBuffer value){
 60         int temp;
 61         for(int i = beginIndex;i<endIndex;i++){
 62             temp = jinWei + array[i] - '0';
 63             jinWei = temp/10;
 64             value.append((char)(temp%10+'0'));
 65         }
 66         return jinWei;
 67     }
 68     
 69     /**
 70      * 功能:较大的非负整数bigNumStr减去较小的非负整数smallNumStr
 71      */
 72     private  StringBuffer plusMinus(String bigNumStr,String smallNumStr){
 73         //把两个数字字符串倒置,并存入字符数组
 74         char [] num1 = new StringBuffer(bigNumStr).reverse().toString().toCharArray();
 75         char [] num2 = new StringBuffer(smallNumStr).reverse().toString().toCharArray();
 76         StringBuffer value = new StringBuffer();
 77         
 78         /*--------------计算减法开始------------------------*/    
 79         int i,temp,jieWei = 0;
 80         for(i = 0;i<smallNumStr.length();i++){
 81             temp = num1[i]  - jieWei - num2[i];
 82             jieWei = oneBitMinus(temp,value,i);    
 83         }
 84         //处理较大数比较小数多出来的位
 85         for(;i<bigNumStr.length();i++){
 86             temp = num1[i] - '0' - jieWei;
 87             jieWei = oneBitMinus(temp,value,i);
 88         }
 89         /*--------------计算减法结束------------------------*/
 90         return deleteZero(value).reverse();
 91     }
 92     /**
 93      * 删去多余的0
 94      */
 95     private StringBuffer deleteZero(StringBuffer str){
 96         int num=0;
 97         for(int i = str.length()-1;i>=0;i--){
 98             if(str.charAt(i) == '0')
 99                 num++;
100             else
101                 break;
102         }
103         if(num != str.length()) 
104             str.setLength(str.length()-num);
105         else
106             str = new StringBuffer("0");
107         return str;
108     }
109     /**
110      * 一位减法
111      */
112     private int oneBitMinus(int flag,StringBuffer value,int num){
113         int jieWei;
114         if(flag <0){
115             value.append((char)(10 +flag + '0'));
116             jieWei = 1;
117         }
118         else{
119             jieWei = 0;
120             value.append((char)(flag + '0'));
121         }
122         return jieWei;
123     }
124     
125     /**
126      * 名称:内部调用的减法。
127      * 功能:两个非负数相减。
128      * 结果:返回运算结果的前后倒置。
129      */
130     private  StringBuffer innerMinus(String str1,String str2){
131         StringBuffer temp;
132         if(Str1ThanStr2(str1,str2))//若str1更大
133             temp =  plusMinus(str1,str2);
134         else{
135             temp = plusMinus(str2,str1);
136             if(!temp.toString().equals("0"))
137                  temp.reverse().append('-').reverse();
138         }
139         return temp;
140     }
141     /**
142      * 判断正负
143      * true -- 非负      false -- 负
144      */
145     public boolean isNoNegative(MyBigInteger t){
146         if(t.data.charAt(0) == '-')
147             return false;
148         return true;
149     }
150     
151     /**
152      * 对外开放的加法接口
153      * 计算str1 + str2
154      */
155     public MyBigInteger Add(MyBigInteger str){
156         //两数都非负
157         if(isNoNegative(this) && isNoNegative(str)) 
158                 data = plusAdd(data.toString(),str.data.toString());
159         else if(!isNoNegative(this) && !isNoNegative(str)){
160                 StringBuffer temp = plusAdd(data.substring(1),str.data.substring(1));
161                 if(!temp.toString().equals("0"))
162                     data =  temp.reverse().append('-').reverse();
163                 else
164                     data = temp;
165             }
166         else if(!isNoNegative(this) && isNoNegative(str))
167                 data = innerMinus(str.data.toString(),data.substring(1));
168         else
169                 data = innerMinus(data.toString(),str.data.substring(1));
170         return this;
171     }
172     /**
173      * 对外开放的减法。
174      * 计算str1 - str2
175      */
176     public MyBigInteger Minus(MyBigInteger t){
177             //两数都为正。
178             if(isNoNegative(this) && isNoNegative(t))
179                 data = innerMinus(this.data.toString(),t.data.toString());    
180             //两数都为负时,需要对innerMinus得到的结果逆转正负。
181             else if(!isNoNegative(this) && !isNoNegative(t))  
182                 data = innerMinus(t.data.substring(1),data.substring(1));        
183             //this 为负,t为非负。
184             else if(!isNoNegative(this) && isNoNegative(t)){
185                 StringBuffer temp = plusAdd(data.substring(1),t.data.toString());
186                 if(!temp.toString().equals("0"))    
187                     data = temp.reverse().append('-').reverse();
188                 else
189                     data = temp;
190             }
191             //this 为非负,str为负。
192             else
193                 data = plusAdd(data.toString(),t.data.substring(1).toString());    
194             return this;
195     }
196     
197     /**
198      * 内部使用的两个正整数乘法
199      */
200     private  StringBuffer plusMulti(StringBuffer str1,StringBuffer str2) {
201         //新建两个StringBuffer,存储两数的前后倒置。
202         StringBuffer num1 = new StringBuffer(str1.substring(0)).reverse();
203         StringBuffer num2 = new StringBuffer(str2.substring(0)).reverse();
204         StringBuffer array = new StringBuffer();
205         //n位数和m位数相乘,得到的结果的位数只能是n+m或者n+m-1。
206         int len = str1.length() + str2.length();
207         for(int i = 0;i<len-1;i++){
208             array.append('0');
209         }
210         //标志n+m位
211         array.append('+'); 
212         
213         //模拟竖式计算    
214         for(int i = 0,j,jinWei = 0 ; i < str2.length() ; i++){
215             jinWei = 0; //进位归位
216             for(j = 0 ; j < str1.length() ; j++){
217                 int temp = (num2.charAt(i)-'0')*(num1.charAt(j)-'0') + jinWei + array.charAt(i+j) - '0';
218                 array.setCharAt(i+j,(char)(temp%10 + '0'));
219                 jinWei = temp /10;
220             }
221             if(jinWei !=0)
222                 array.setCharAt(i+j, (char)(jinWei +'0'));
223         }
224         if(array.charAt(len -1) == '+')
225             array.setLength(len-1);
226         return  array.reverse();
227     }
228     /**
229      * 对外开放的乘法
230      */
231     public MyBigInteger Multi(MyBigInteger t){
232         //两数至少有一个为0
233         if(data.toString().equals("0") || t.data.toString().equals("0"))
234             data = new StringBuffer("0");
235         else{
236             //两数都是正数
237             if(isNoNegative(this) && isNoNegative(t))
238                 data = plusMulti(data,t.data).reverse();
239             //两数都是负数
240             else if(!isNoNegative(this) && !isNoNegative(t))
241                 data = plusMulti(new StringBuffer(data.substring(1)),new StringBuffer(t.data.substring(1)));    
242             
243             //两数一正一负
244             else if(isNoNegative(this) && !isNoNegative(t))
245                 data =     plusMulti(data,new StringBuffer(t.data.substring(1))).reverse().append('-').reverse();    
246             else
247                 data = plusMulti(new StringBuffer(data.substring(1)),t.data).reverse().append('-').reverse();
248         }
249         return this;
250     }
251     /**
252      * 两个非负数相除,除数不为0
253      * 返回:没有前后倒置的正确的结果
254      */
255     private StringBuffer plusDivide(String str1,String str2){
256         StringBuffer division = new StringBuffer();
257         StringBuffer remain   = new StringBuffer();
258         
259         int end = 0;
260         boolean  flag = false;
261         while(end < str1.length()){
262             remain.append(str1.charAt(end));
263             if(Str1ThanStr2(remain.toString(),str2)){//能整除
264                 flag = true;
265                 int fullNum = Greatst(remain,str2);
266                 StringBuffer fullNumStr2 = plusMulti(new StringBuffer(str2),new StringBuffer(""+fullNum));
267                 division.append(""+fullNum);
268                 remain = plusMinus(remain.toString(),fullNumStr2.toString());
269             }
270             else if(flag)//不够除,补0
271                 division.append("0");
272             if(remain.toString().equals("0"))
273                 remain.setLength(0);
274             end++;
275         }
276         if(division.length() == 0){
277             return division.append('0');
278         }
279         return division;
280     }
281     /**
282      * 对外开放的减法
283      */
284     public MyBigInteger Divide(MyBigInteger t){
285         if(t.data.toString().equals("0"))
286             System.out.println("除零异常");
287         else{
288             if(isNoNegative(this) && isNoNegative(t))
289                 data = plusDivide(data.toString(),t.data.toString());
290             else if(!isNoNegative(this) && !isNoNegative(t)){
291                 data = plusDivide(data.substring(1),t.data.substring(1));
292             }
293             else{
294                 StringBuffer temp;
295                 if(!isNoNegative(this) && isNoNegative(t))
296                      temp = plusDivide(data.substring(1),t.data.toString());
297                 else
298                      temp = plusDivide(data.toString(),t.data.substring(1));
299                 if(temp.toString().equals("0"))
300                     data = temp;
301                 else
302                     data = temp.reverse().append('-').reverse();
303             }
304         }
305         return this;
306     }
307  
308     /*
309      * 找出最大
310      */
311     private  int Greatst(StringBuffer str1,String str2){
312         for(int i = 1;i<10;i++){
313             StringBuffer num2 = new StringBuffer(str2);
314             for(int j =0;j<i;j++){//(i +1)倍
315                 num2 = plusAdd(num2.toString(),str2);
316             }
317             if(!Str1ThanStr2(str1.toString(),num2.toString())){
318                 return i;
319             }
320         }
321         return -1;
322     }
323     /**
324      * 判断str1、str2的大小
325      * 返回:str1>= str2 -----true           
326      *      str1< str2 -----false
327      */
328     private static boolean Str1ThanStr2(String str1,String str2){
329         boolean flag;//1 代表str1大些;2代表str2大些
330         //判断两个非负数,谁大。
331         if(str1.length() == str2.length()){
332             if(str1.compareTo(str2)<0)
333                 flag = false;
334             else   
335                 flag =true;
336         }
337         else{
338             if(str1.length() >str2.length())
339                 flag = true;
340             else
341                 flag = false;
342         }
343         return flag;
344     }
345     
346     
347     public static void main(String[] args) {
348         MyBigInteger a1 = new MyBigInteger("175");
349         MyBigInteger a2 = new MyBigInteger("231");
350         MyBigInteger a3 = new MyBigInteger("143");
351         MyBigInteger a4 = new MyBigInteger("-1978654");
352         MyBigInteger b = new MyBigInteger("-54");
353         MyBigInteger b1 = new MyBigInteger("0");
354         //175 + 231 - 143
355         System.out.println(a1.Add(a2).Minus(a3));
356         //(175 + 231 - 143)*(-1978654)
357         System.out.println(a1.Multi(a4));
358         //(175 + 231 - 143)*(-1978654)/(-54)
359         System.out.println(a1.Divide(b));
360         //0
361         System.out.println(a1.Multi(b1));
362     }
363 }