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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM