作者:Byte_Liu 來源:http://byteliu.com/categories/
題目:在不使用BigInteger類的情況下,如何計算兩個大正整數的和?
程序不可能通過一條指令計算出兩個大整數的和,但我們可以把一個大運算拆分成多個小運算, 像小學生一樣列豎式進行按位運算。這里還有一個問題,我們都知道long類型的取值范圍是:
最小值:Long.MIN_VALUE=-9223372036854775808 (-2的63次方)
最大值:Long.MAX_VALUE=9223372036854775807 (2的63次方-1)
如果大整數超出了long類型能表示的范圍,我們如何存儲這樣的整數呢?
很容易想到,使用數組存儲即可,數組的每一個元素對應大整數的每一個位數。
在程序中列出的 “豎式” 究竟是什么樣子呢?
我們以 426709752318 + 95481253129 為例,來看看大整數相加的詳細步驟:

第一步,把整數倒序存儲,整數的個位存于數組0下標位置,最高位存于數組長度-1下標位置。之所以倒序存儲,更加符合我們從左到右訪問數組的習慣。

第二步,創建結果數組,結果數組的最大長度是較大整數的位數+1,原因很明顯。

第三步,遍歷兩個數組,從左到右按照對應下標把元素兩兩相加,就像小學生計算豎式一樣。
例子中,最先相加的是數組A的第1個元素8和數組B的第1個元素9,結果是7,進位1。把7填充到Result數組的對應下標,進位的1填充到下一個位置:

第二組相加的是數組A的第2個元素1和數組B的第2個元素2,結果是3,再加上剛才的進位1,把4填充到Result數組的對應下標:

第三組相加的是數組A的第3個元素3和數組B的第3個元素1,結果是4,把4填充到Result數組的對應下標:

第四組相加的是數組A的第4個元素2和數組B的第4個元素3,結果是5,把5填充到Result數組的對應下標:

以此類推……一直把數組的所有元素都相加完畢:

第四步,把Result數組的全部元素再次逆序,去掉首位的,就是最終結果:

如果給定的大整數最長位數是n,那么創建數組、按位運算、結果逆序的時間復雜度各自都是O(n),整體時間復雜度就是O(n)。
/** * 類描述: 大整數求和 * * @author yugu.lx 2018/10/20 23:02 PM */ public class BigNumSum { public static void main(String args[]) { char c = '7'; int i = c; //如何把 char ‘7’ 轉為 int 7, 不能直接int i= '7'轉化,那樣得到是‘7’的Ascii值,即int 55 System.out.println(i); //可以采用如下方式進行操作把 char ‘7’ 轉為 int 7;‘0’的Ascii值是48 int ii = c - '0'; System.out.println(ii); System.out.println(new BigNumSum().bigNumSum("426709752318", "95481253129")); } private String bigNumSum(String bigNum1, String bigNum2) { char[] num1Chars = new StringBuilder(bigNum1).reverse().toString().toCharArray(); char[] num2Chars = new StringBuilder(bigNum2).reverse().toString().toCharArray(); int[] result = new int[Math.max(num1Chars.length, num1Chars.length) + 1]; for (int i = 0; i < result.length; i++) { if (i < num1Chars.length) { result[i] += num1Chars[i] - '0'; carryCover(result, i); } if (i < num2Chars.length) { result[i] += num2Chars[i] - '0'; carryCover(result, i); } } return transferToIntString(result); } /** * 進位操作 * * @param result * @param i */ private void carryCover(int[] result, int i) { if (i == result.length - 1) { return; } if (result[i] >= 10) { result[i] -= 10; result[i + 1] += 1; } } /** * 把數組轉化成字符串 * * @param array * @return */ private String transferToIntString(int[] array) { StringBuilder sb = new StringBuilder(); for (int i = array.length - 1; i >= 0; i--) { //如果最高位為0的話則去掉 if (i == array.length - 1 && array[i] == 0) { continue; } sb.Append(array[i]); } return sb.toString(); } }