大数乘法的主要解法如下:
解法:
0、最简单的模拟手算的方法(O(N^2))
1、分治乘法(最简单的是Karatsuba乘法(http://blog.csdn.net/sunnyyoona/article/details/43234889),一般化以后有Toom-Cook乘法);
2、快速傅里叶变换FFT(为了避免精度问题,可以改用快速数论变换FNTT),时间复杂度O(NlgNlglgN)。具体可参照Schönhage;
3、中国剩余定理(把每个数分解到一些互素的模上,然后每个同余方程对应乘起来就行);
4、刚看到一个在渐进意义上FNTT还快的算法Furer’s algorithm,不过好像不太实用。下面的reference[3]给出了模运算的版本。
模拟手算法代码如下:
public class Solution {
public String multiply(String num1, String num2) {
int[] result = new int[num1.length() + num2.length()+1];
boolean resultNegative = false;
if (num1.startsWith("-")){
resultNegative = !resultNegative;
num1 = num1.substring(1);
}
if (num2.startsWith("-")){
resultNegative = !resultNegative;
num2 = num2.substring(1);
}
int tmp1 = 0, i = 0, j = 0, ii = 0, jj = 0, carry = 0;
//two positive num(string) multiply
for(ii = num1.length() - 1; ii >= 0; ii --){ //index of string
carry = 0;
for(jj = num2.length() - 1; jj >= 0; jj --){
i = num1.length() - 1 - ii;
j = num2.length() - 1 - jj;
tmp1 = result[i+j] + (num1.charAt(ii) - '0') * (num2.charAt(jj) - '0') + carry;
result[i+j] = tmp1 % 10;
carry = tmp1 / 10;
}
result[i+j+1] += carry; //deal with the maximum carry.
}
StringBuilder sb = new StringBuilder();
boolean startZero = true;
for (i = num1.length() + num2.length(); i >= 0; i --){
if (startZero == true){
if (result[i] != 0){
sb.append(result[i]);
startZero = false;
}
}else{
sb.append(result[i]);
}
}
if (sb.length() != 0 && resultNegative == true)
sb.insert(0, '-');
if (sb.length() != 0){
return sb.toString();
}else
return "0";
}
}
高级算法以后再补