題目:兩個非常大的數字相乘(相加,相減)
該題目在java中可以使用BigInteger類中的方法來實現。否則的話可以使用如下方式來實現。
大數相乘:假設有A和B兩個大數,位數分別爲a和b。根據我們平常手動計算乘法的方式可以看出,最終的結果的位數c一定小於等於a+b,我們可以舉一個簡單的例子來說明,99*999=98901,最終結果是五位(a+b)。下面我們根據98*765 = 74970來看看結果中的每一位是怎麼得來的,最後一位0是A的最後一位8和B的最後一位5的乘機除10取餘得到的,結果的倒數第二位7是A的倒數第二位9和B的最後一位5的乘積45與A的最後一位8和B的倒數第二位6的乘積48之和93然後加上上一位的進位4得到97然後在除10取餘得到的7……依次進行下去就可以得到最終結果。
下面來總結一下規律:A中的第i位與B的第j位之積最終會存放到結果的第i+j位中(i和j都是從後往前數),所以我們可以先進行結果中每一位的計算,完成所有計算後在進行進位的計算。爲了將i和j從0開始計算,我們先將字符串A和B進行逆轉,然後在進行計算的時候就可以從0開始了。具體程序如下:
- public static void bigNumberSimpleMulti(String f, String s) {
- System.out.print("乘法:\n" + f + "*" + s + "=");
- // 獲取首字符,判斷是否是符號位
- char signA = f.charAt(0);
- char signB = s.charAt(0);
- char sign = '+';
- if (signA == '+' || signA == '-') {
- sign = signA;
- f = f.substring(1);
- }
- if (signB == '+' || signB == '-') {
- if (sign == signB) {
- sign = '+';
- } else {
- sign = '-';
- }
- s = s.substring(1);
- }
- // 將大數翻轉並轉換成字符數組
- char[] a = new StringBuffer(f).reverse().toString().toCharArray();
- char[] b = new StringBuffer(s).reverse().toString().toCharArray();
- int lenA = a.length;
- int lenB = b.length;
- // 計算最終的最大長度
- int len = lenA + lenB;
- int[] result = new int[len];
- // 計算結果集合
- for (int i = 0; i < a.length; i++) {
- for (int j = 0; j < b.length; j++) {
- result[i + j] += (int) (a[i] - '0') * (int) (b[j] - '0');
- }
- }
- // 處理結果集合,如果是大於10的就向前一位進位,本身進行除10取餘
- for (int i = 0; i < result.length; i++) {
- if (result[i] > 10) {
- result[i + 1] += result[i] / 10;
- result[i] %= 10;
- }
- }
- StringBuffer sb = new StringBuffer();
- // 該字段用於標識是否有前置0,如果是0就不需要打印或者存儲下來
- boolean flag = true;
- for (int i = len - 1; i >= 0; i--) {
- if (result[i] == 0 && flag) {
- continue;
- } else {
- flag = false;
- }
- sb.append(result[i]);
- }
- if (!sb.toString().equals("")) {
- if (sign == '-') {
- sb.insert(0, sign);
- }
- } else {
- sb.append(0);
- }
- // 返回最終結果
- System.out.println(sb.toString());
- }
大數相加:和相乘是類似的,不同的地方只是result結果集的長度,其值爲較長字符串的長度加一。具體代碼如下:
- public String bigNumberAdd(String f, String s) {
- //翻轉兩個字符串,並轉換成數組
- char[] a = new StringBuffer(f).reverse().toString().toCharArray();
- char[] b = new StringBuffer(s).reverse().toString().toCharArray();
- int lenA = a.length;
- int lenB = b.length;
- //計算兩個長字符串中的較長字符串的長度
- int len = lenA > lenB ? lenA : lenB;
- int[] result = new int[len + 1];
- for (int i = 0; i < len + 1; i++) {
- //如果當前的i超過了其中的一個,就用0代替,和另一個字符數組中的數字相加
- int aint = i < lenA ? (a[i] - '0') : 0;
- int bint = i < lenB ? (b[i] - '0') : 0;
- result[i] = aint + bint;
- }
- //處理結果集合,如果大於10的就向前一位進位,本身進行除10取餘
- for (int i = 0; i < result.length; i++) {
- if (result[i] > 10) {
- result[i + 1] += result[i] / 10;
- result[i] %= 10;
- }
- }
- StringBuffer sb = new StringBuffer();
- //該字段用於標識是否有前置0,如果有就不要存儲
- boolean flag = true;
- for (int i = len; i >= 0; i--) {
- if (result[i] == 0 && flag) {
- continue;
- } else {
- flag = false;
- }
- sb.append(result[i]);
- }
- return sb.toString();
- }
- public static String bigNumberSub(String f, String s) {
- System.out.print("減法:" + f + "-" + s + "=");
- // 將字符串翻轉並轉換成字符數組
- char[] a = new StringBuffer(f).reverse().toString().toCharArray();
- char[] b = new StringBuffer(s).reverse().toString().toCharArray();
- int lenA = a.length;
- int lenB = b.length;
- // 找到最大長度
- int len = lenA > lenB ? lenA : lenB;
- int[] result = new int[len];
- // 表示結果的正負
- char sign = '+';
- // 判斷最終結果的正負
- if (lenA < lenB) {
- sign = '-';
- } else if (lenA == lenB) {
- int i = lenA - 1;
- while (i > 0 && a[i] == b[i]) {
- i--;
- }
- if (a[i] < b[i]) {
- sign = '-';
- }
- }
- // 計算結果集,如果最終結果爲正,那麼就a-b否則的話就b-a
- for (int i = 0; i < len; i++) {
- int aint = i < lenA ? (a[i] - '0') : 0;
- int bint = i < lenB ? (b[i] - '0') : 0;
- if (sign == '+') {
- result[i] = aint - bint;
- } else {
- result[i] = bint - aint;
- }
- }
- // 如果結果集合中的某一位小於零,那麼就向前一位借一,然後將本位加上10。其實就相當於借位做減法
- for (int i = 0; i < result.length - 1; i++) {
- if (result[i] < 0) {
- result[i + 1] -= 1;
- result[i] += 10;
- }
- }
- StringBuffer sb = new StringBuffer();
- // 如果最終結果爲負值,就將負號放在最前面,正號則不需要
- if (sign == '-') {
- sb.append('-');
- }
- // 判斷是否有前置0
- boolean flag = true;
- for (int i = len - 1; i >= 0; i--) {
- if (result[i] == 0 && flag) {
- continue;
- } else {
- flag = false;
- }
- sb.append(result[i]);
- }
- // 如果最終結果集合中沒有值,就說明是兩值相等,最終返回0
- if (sb.toString().equals("")) {
- sb.append("0");
- }
- // 返回值
- System.out.println(sb.toString());
- return sb.toString();
- }
在上述的各中計算過程中有幾點需要說明:大數相加的時候沒有判斷數字的正負,如果都是正數,那麼就可以按照正數相加來計算,如果是一正一負可以轉換成大整數相減,兩個負數可以先保存符號,然後相加。