問題分析:
加減運算:
兩數進行加減,都可以轉為兩個基本運算:
- 兩個非負數相加--------------- 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 分別為被加數 、加數,則最終結果只可能是以下情況:
- num1 非負數 num2 非負數
- num1 負數 num2 負數 、
- num1 非負數 num2 負數
- num1 負數 num2 非負數
上面四種情況可以轉為:
- plusAdd(num1,num2)
- - plusAdd(- num1,- num2)
- plusMinus(num1,- num2)
- 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 }