贪心算法-大整数乘法/加法/减法
2017-02-20 17:39
330 查看
设有两个大整数相乘,X=61438521,Y=94736407.那么XY=5820464730934047.易知我么的算法需要O(N²)即O(8²)次操作.
如果我们把X和Y都拆成两半,由最高几位和最低几位组成.那么XL=6143,XR=8521,YL=9473,YR=6470.于是X=XL*10^4+XR,Y=YL*10^4+YR.可以得到
XY=XL*YL*10^8+(XL*YR+XR*YL)*10^4+XRYR
显然这个式子就是由4个乘法组成的,每一个都是原问题的一半,而10^8,10^4的乘法只是添一些0,于是可以得到递归:T(N)=4T(N/2)+O(N)..
我们按照主定理(相关资料查阅维基百科),可以求得算法复杂度仍然是O(N²).并没有改进这个问题.
观察XL*YR+XR*YL,可以分解为(XL-XR)(YR-YL)+XL*YL+XR*YR,我们仅需要算前面一项,后面的两项已经计算过了.于是得到了T(N)=3T(N/2)+O(N).,按照主定理,可得T(N)=O(N^1.59).当然对于每一个乘积我们还可以继续递归下去,一般到四位数就不用递归了.
代码:
算法并不复杂,但是处理符号什么的还是比较麻烦的,而且加法减法啥的都要自己去实现.
如果我们把X和Y都拆成两半,由最高几位和最低几位组成.那么XL=6143,XR=8521,YL=9473,YR=6470.于是X=XL*10^4+XR,Y=YL*10^4+YR.可以得到
XY=XL*YL*10^8+(XL*YR+XR*YL)*10^4+XRYR
显然这个式子就是由4个乘法组成的,每一个都是原问题的一半,而10^8,10^4的乘法只是添一些0,于是可以得到递归:T(N)=4T(N/2)+O(N)..
我们按照主定理(相关资料查阅维基百科),可以求得算法复杂度仍然是O(N²).并没有改进这个问题.
观察XL*YR+XR*YL,可以分解为(XL-XR)(YR-YL)+XL*YL+XR*YR,我们仅需要算前面一项,后面的两项已经计算过了.于是得到了T(N)=3T(N/2)+O(N).,按照主定理,可得T(N)=O(N^1.59).当然对于每一个乘积我们还可以继续递归下去,一般到四位数就不用递归了.
代码:
public class BigMultiply { //大整数相乘 public static String multiply(String x, String y) { int flag1 = 0;//x的符号位 int flag2 = 0;//y的符号位 if (x.charAt(0) == '-') {//处理符号 x = x.substring(1);//先把符号位截掉 flag1 = 1; } if (y.charAt(0) == '-') { y = y.substring(1); flag2 = 1; } String flag = (flag1 ^ flag2) == 1 ? "-" : "";//相乘即异或之后符号位 if (x.length() < y.length())//保证x的位数更大 return flag + multiply(y, x); if (x.length() <= 4) return flag + Integer.parseInt(x) * Integer.parseInt(y);//少于等于四位数直接计算了 if (x.length() % 2 == 0) {//x位数是偶数 就把y补成和x一样长 while (x.length() > y.length()) y = "0" + y; } else {//x位数不是偶数 就先把x补成偶数 再把y补成和x一样长 x = "0" + x; while (x.length() > y.length()) y = "0" + y; } String xl = x.substring(0, x.length() / 2); String xr = x.substring(x.length() / 2); String yl = y.substring(0, y.length() / 2); String yr = y.substring(y.length() / 2); String D1 = minus(xl, xr);//xl-xr String D2 = minus(yr, yl);//yr-yl String xlyl = multiply(xl, yl);//xl*yl String xryr = multiply(xr, yr);//xr*yr String D3 = add(multiply(D1, D2) + "", add(xlyl, xryr));//D1*D2+Xl*Yl+Xr*Yr return flag + add(shift(xlyl, x.length()), add(shift(D3, x.length() / 2), xryr)); //Xl*Yl*10^n+D3*10^(n/2)+Xr*Yr } //大数相减 带符号处理 public static String minus(String x, String y) { int large = compare(x, y); String flag = large >= 0 ? "" : "-";//加上符号 if (large == 0) return "0"; else if (large > 0)//转化成大的减小的 return minusBigNum(x, y); else return flag + minusBigNum(y, x); } //大数相减 private static String minusBigNum(String x, String y) {//大数减小数 int len = x.length(); while (len > y.length()) y = "0" + y; StringBuilder result = new StringBuilder(); int flag = 0;//表示是否进位 for (int i = len - 1; i >= 0; i--) { int xs = Integer.parseInt(String.valueOf(x.charAt(i))); int ys = Integer.parseInt(String.valueOf(y.charAt(i))); if (xs + flag >= ys) {//别忘了把flag加上 result.append(xs - ys + flag); flag = 0; } else { result.append(10 + xs - ys + flag); flag = -1; } } return clearZero(result.reverse().toString()); } //大数相加 public static String add(String x, String y) { if (x.charAt(0) == '-') {//先处理符号 x = x.substring(1); if (y.charAt(0) == '-') { y = y.substring(1); return "-" + add(x, y); } else return minus(y, x); } if (y.charAt(0) == '-') { y = y.substring(1); return minus(x, y); } if (x.length() < y.length()) return add(y, x);//保证x的位数更大 int len = x.length(); while (len > y.length())//补位使位数相等 y = "0" + y; StringBuilder result = new StringBuilder(); int flag = 0;//表示是否进位 for (int i = len - 1; i >= 0; i--) { int xs = Integer.parseInt(String.valueOf(x.charAt(i))); int ys = Integer.parseInt(String.valueOf(y.charAt(i))); if (xs + ys + flag > 9) {//别忘了把flag加上 result.append(xs + ys - 10 + flag); flag = 1; } else { result.append(xs + ys + flag); flag = 0; } } if (flag != 0) result.append(1); return clearZero(result.reverse().toString()); } //计算10n次方的 就是后面加0 public static String shift(String x, int n) { for (int j = 0; j < n; j++) { x += "0"; } return x; } //消除0 private static String clearZero(String str) { int j = 0; while (j < str.length() && str.charAt(j) == '0') { j++; } return str.substring(j); } //比较两个数的大小 private static int compare(String x, String y) { if (x.length() > y.length()) return 1; else if (x.length() < y.length()) return -1; else { int index = 0; while (index < x.length() && x.charAt(index) == y.charAt(index)) index++; if (index == x.length()) return 0; else { return x.charAt(index) > y.charAt(index) ? 1 : -1; } } } public static void main(String[] args) { System.out.println(multiply("-61438521", "94736407")); System.out.println(multiply("-3124234254543411432432422238221342421", "-2423442342342342342342342323423445345699")); } }
算法并不复杂,但是处理符号什么的还是比较麻烦的,而且加法减法啥的都要自己去实现.
相关文章推荐
- 大整数运算之 大整数加法、减法、乘法
- 整数高精度运算的库(加法,减法,乘法,除法,取模)
- 大整数加法减法与乘法
- 使用main函数的参数,实现一个整数计算器,程序可以接受三个参数,第一个参数“-a”选项执行加法,“-s”选项执行减法,“-m”选项执行乘法,“-d”选项执行除法,后面两个参数为操作数。
- 大整数算法[08] 有符号加法和减法
- 大整数的加法、减法和乘法
- 使用main函数的参数,实现一个整数计算器,程序可以接受三个参数,第一个参数“-a”选项执行加法,“-s”选项执行减法,“-m”选项执行乘法,“-d”选项执行除法,后面两个参数为操作数。
- 使用main函数的参数,实现一个整数计算器,程序可以接受三个参数,第一个参数“-a”选项执行加法,“-s”选项执行减法,“-m”选项执行乘法,“-d”选项执行除法,后面两个参数为操作数。
- 大型整数运算:加法, 减法, 乘法
- 大整数的乘法、加法、减法
- 值得注意的算法问题,“两次减法操作”竟然比“一次2倍乘法和一次加法”要慢一秒
- 整数大数模拟 高精度加法 高精度减法 高精度乘法 高精度除法 c/c++ java
- 值得注意的算法问题,“两次减法操作”竟然比“一次2倍乘法和一次加法”要慢一秒
- 使用main函数的参数,实现一个整数计算器,程序可以接受三个参数,第一个参数“-a”选项执行加法,“-s”选项执行减法,“-m”选项执行乘法,“-d”选项执行除法,后面两个参数为操作数。
- 使用main函数的参数,实现一个整数计算器,程序可以接受三个参数,第一个参数“-a”选项执行加法,“-s”选项执行减法,“-m”选项执行乘法,“-d”选项执行除法,后面两个参数为操作数。
- 实现一个整数计算器,程序可以接受三个参数,第一个参数“-a”选项执行加法,“-s”选项执行减法,“-m”选项执行乘法,“-d”选项执行除法,后面两个参数为操作数。 例如:输入t
- 大精度整数三种运算(加法,减法,乘法)
- 使用main函数的参数,实现一个整数计算器,程序可以接受三个参数,第一个参数“-a”选项执行加法,“-s”选项执行减法,“-m”选项执行乘法,“-d”选项执行除法,后面两个参数为操作数。
- 算法(求对输入的N个数进行加法或减法运算,得到最小的正整数的组合.)
- 大整数运算之 大整数加法、减法、乘法