大数相乘
2017-08-02 17:52
204 查看
一、找规律
首先观察手工两数相乘的规律:如765*98,手工过程如下表所示
由上表过程可得出如下规律:
(1)两数相乘的最终结果的位数不超过两数的位数之和,取极端例子99*999=98901;
(2)A中第i位与B中第j位相乘的结果放在第i+j位中,其中i,j都是从后往前数;
(3)第i个数上的进位加到第i+1个数上;
二、实现步骤
1、合法性:判断A、B字符串首字符是否含有符号位“+”和“-”,若含有,从第二个字符开始计算;
2、翻转:将A、B字符串翻转并转换成数组;
3、构造结果集:构造结果数组result,大小为A、B除去符号位长度之和;
4、计算:遍历A,B数组,A中第i位与B中第j位相乘的结果放在结果集的第i+j位中;
5、进位:遍历结果集,如果结果集的数大于等于10,进行进位,进位规则为第i个数上的进位加到第i+1个数上;
6、过滤:若结果集中有前置0,则需要删除前置0。如果有负符号位加上符号位。
三、代码实现
public static String bigIntMultiply(String A, String B) { //判断A、B字符串首字符是否含有符号位“+”和“-” char chA = A.charAt(0); if (chA == '+' || chA == '-') A = A.substring(1); char chB = B.charAt(0); if (chB == '+' || chB == '-') B = B.substring(1); //将A、B字符串翻转并转换成数组; char[] s = new StringBuffer(A).reverse().toString().toCharArray(); char[] t = new StringBuffer(B).reverse().toString().toCharArray(); //构造结果数组result,大小为s、t除去符号位长度之和; int[] result = new int[s.length + t.length]; //遍历A,B数组,A中第i位与B中第j位相乘的结果放在结果集的第i+j位中; for (int i = 0; i < s.length; i++) { for (int j = 0; j < t.length; j++) result[i + j] += (int) (s[i] - '0') * (int) (t[j] - '0'); } //遍历结果集,如果结果集的数大于等于10,进行进位,进位规则为第i个数上的进位加到第i+1个数上; for (int i = 0; i < result.length; i++) { if (result[i] >=10) { result[i + 1] += result[i] / 10; result[i] = result[i] % 10; } } //若结果集中有前置0,则需要删除前置0。 StringBuffer sb = new StringBuffer(); boolean NonZero = false; for (int i = result.length - 1; i >= 0; i--) { if (result[i] != 0) NonZero = true; if (NonZero) sb.append(result[i]); } //如果有负符号位加上符号位 if ((chA == '-' && chB != '-') || (chA != '-' && chB == '-')) sb.insert(0, "-"); return sb.toString(); }
首先观察手工两数相乘的规律:如765*98,手工过程如下表所示
下标 | 4 | 3 | 2 | 1 | 0 |
A(i) | | | 7 | 6 | 5 |
B(j) | | | | 9 | 8 |
中间过程 | | 6 | (56+5)1 | (48+4)2 | (40)0 |
6 | (63+5)8 | (54+4)8 | (45)5 | | |
result | 7 | 4 | 9 | 7 | 0 |
(1)两数相乘的最终结果的位数不超过两数的位数之和,取极端例子99*999=98901;
(2)A中第i位与B中第j位相乘的结果放在第i+j位中,其中i,j都是从后往前数;
(3)第i个数上的进位加到第i+1个数上;
二、实现步骤
1、合法性:判断A、B字符串首字符是否含有符号位“+”和“-”,若含有,从第二个字符开始计算;
2、翻转:将A、B字符串翻转并转换成数组;
3、构造结果集:构造结果数组result,大小为A、B除去符号位长度之和;
4、计算:遍历A,B数组,A中第i位与B中第j位相乘的结果放在结果集的第i+j位中;
5、进位:遍历结果集,如果结果集的数大于等于10,进行进位,进位规则为第i个数上的进位加到第i+1个数上;
6、过滤:若结果集中有前置0,则需要删除前置0。如果有负符号位加上符号位。
三、代码实现
public static String bigIntMultiply(String A, String B) { //判断A、B字符串首字符是否含有符号位“+”和“-” char chA = A.charAt(0); if (chA == '+' || chA == '-') A = A.substring(1); char chB = B.charAt(0); if (chB == '+' || chB == '-') B = B.substring(1); //将A、B字符串翻转并转换成数组; char[] s = new StringBuffer(A).reverse().toString().toCharArray(); char[] t = new StringBuffer(B).reverse().toString().toCharArray(); //构造结果数组result,大小为s、t除去符号位长度之和; int[] result = new int[s.length + t.length]; //遍历A,B数组,A中第i位与B中第j位相乘的结果放在结果集的第i+j位中; for (int i = 0; i < s.length; i++) { for (int j = 0; j < t.length; j++) result[i + j] += (int) (s[i] - '0') * (int) (t[j] - '0'); } //遍历结果集,如果结果集的数大于等于10,进行进位,进位规则为第i个数上的进位加到第i+1个数上; for (int i = 0; i < result.length; i++) { if (result[i] >=10) { result[i + 1] += result[i] / 10; result[i] = result[i] % 10; } } //若结果集中有前置0,则需要删除前置0。 StringBuffer sb = new StringBuffer(); boolean NonZero = false; for (int i = result.length - 1; i >= 0; i--) { if (result[i] != 0) NonZero = true; if (NonZero) sb.append(result[i]); } //如果有负符号位加上符号位 if ((chA == '-' && chB != '-') || (chA != '-' && chB == '-')) sb.insert(0, "-"); return sb.toString(); }