将一个规模为N的问题,分解成K个规模较小的子问题,这些子问题相互独立且月原问题性质相同,求解出子问题的解,合并获得原问题的解java
(1)程序有时须要处理大整数,java.math包中的BigInteger类提供任意精度的整数运算,可使用构造方法:算法
public BigInteger(String VAL)构造一个十进制的BigInteger对象,该构造方法能够发生NumberFormatException异常,也就是说,字符串参数VAL中若是含有非数字字符就会发生NumberFormatException异常。数组
(2)BigInteger类的经常使用方法:ide
public BigInteger add(BigInteger val) 返回当前大整数对象与参数指定的大整数对象的和code
public BigInteger subtract(BigInteger val) 返回当前大整数对象与参数指定的大整数对象的差orm
public BigInteger multiply(BigInteger val) 返回当前大整数对象与参数指定的大整数对象的积对象
public BigInteger devide(BigInteger val) 返回当前大整数对象与参数指定的大整数对象的商递归
public BigInteger remainder(BigInteger val) 返回当前大整数对象与参数指定的大整数对象的余ip
public int compareTo(BigInteger val) 返回当前大整数对象与参数指定的大整数对象的比较结果,返回值是一、-一、0,分别表示当前大整数对象大于、小于或等于参数指定的大整数。ci
public BigInteger abs() 返回当前大整数对象的绝对值
public BigInteger pow(int exponent) 返回当前大整数对象的exponent次幂。
public String toString() 返回当前当前大整数对象十进制的字符串表示。
public String toString(int p) 返回当前大整数对象p进制的字符串表示。
可是这篇文章不用这个java内置的方法来实现大数乘法
import java.util.*; import java.math.*; public class NumMul{ public static void main(String args[]){ Scanner cin = new Scanner(System.in); BigInteger a, b; while(cin.hasNext()){ a = cin.nextBigInteger(); b = cin.nextBigInteger(); System.out.println(a.multiply(b)); } } }
分治法能解决的问题通常具备如下几个特征:
该问题的规模缩小到必定程度就能够容易的解决;
该问题能够分解为若干个规模较小的相同问题,即该问题具备最优子结构性质;
利用该问题分解出子问题的解,能够合并为该问题的解;
该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子子问题;
分治算法大多采用递归实现,第二条特征就反应了递归思想的引用。
若是知足了第一条特征和第二条特征,不知足第三条特征,能够考虑用贪心法或动态规划法。
若是不知足第四条特征,也能够用分治法,可是要作不少没必要要的工做,重复的解公共的子问题,因此通常用动态规划法比较好。
将两个整数分别一分为二:
X = A*10^(n/2) + B Y = C*10^(n/2) + D X*Y = (A*10^(n/2) + B)*( C*10^(n/2) + D) = A*C*10^n + A*D*10^(n/2) + B*C*10^(n/2) + B*D
可是这样作并无减小直接相乘的的时间复杂度,因此要继续减小乘法的次数
X*Y = (A*10^(n/2) + B)*( C*10^(n/2) + D) = A*C*10^n + A*D*10^(n/2) + B*C*10^(n/2) + B*D = A*C*10^n + ((A+B)(C+D) – A*C – B*D)*10*(n/2) + B*D 或者:= A*C*10^n + ((A-B)(D-C) + A*C + B*D)*10*(n/2) + B*D
而后利用上面的公式写递归就行了
代码以下:
public class BigDataRide { public static int sign(long a) { return a < 0 ? -1 : 1; } public static double bigdataride(long x,long y,int n) { x = Math.abs(x); y = Math.abs(y); if (n == 1) { return x * y; } else { if (n%2==1) { n = n - 1; //对奇数的操做 } long a = x / Math.round(Math.pow( 10 , (n / 2))); long b = x - a * Math.round(Math.pow( 10 , (n / 2))); long c = y / Math.round(Math.pow( 10 , (n / 2))); long d = y - c * Math.round(Math.pow( 10 , (n / 2))); double ac = bigdataride(a,c,n/2);//递归计算a*c double bd = bigdataride(b,d,n/2);//计算b*d long aJb = a + b; long cJd = c + d; double abcd = bigdataride(aJb,cJd,n/2); return (ac*Math.pow(10,n) + (abcd - ac - bd)*Math.pow(10,n/2) +bd); } } public static void main(String[] args) { // 大整数相乘 long x = 12234L; long y = 45243L; String sx = String.valueOf(x); int n = sx.length(); long sig = sign(x)*sign(y); double s = bigdataride(x,y,n); System.out.println("大数相乘的计算结果为:"+s*sig); } }
模拟乘法
将两个数分别存入两个数组,而后根据乘法规则两层for循环分别让数字相乘,并存入一个新的数组,大体为这样:result[a+b] += num1[a]*num2[b];
,如今这个result里存储的就是一个非个位数的临时结果,只须要作后将这个临时结果分别进位即可获得最终结果
代码以下:
import java.util.Scanner; //建立类largenumberOperationMultiply public class largenumberOperationMultiply { //定义方法multiply的功能 public String multiply(String str1,String str2){ int[] num1 = new int[str1.length()]; int[] num2 = new int[str2.length()]; int[] result = new int[str1.length() + str2.length()]; //将两个字符串转成整型数组,顺序转换,数组下标越小,数字对应的位数越高 for (int i = 0;i < str1.length(); i++){ num1[i] = Integer.parseInt(str1.substring(i,i+1)); } for (int i = 0;i < str2.length(); i++){ num2[i] = Integer.parseInt(str2.substring(i,i+1)); } //两大数相乘 for (int a = 0;a < str1.length(); a++){ for (int b = 0;b < str2.length(); b++){ result[a+b] += num1[a]*num2[b]; } } ////判断是否须要进位,满10进1,由于存储顺序与位数高低相反,因此采用逆序进位 int temp; for (int k = result.length-1; k > 0; k--){ temp=result[k]/10; //数组下标大的向数组下标小的进位 result[k-1] += temp; result[k] = result[k]%10; } //将结果数组逆序转化为字符串 String resultstr = ""; for (int i = 0; i < result.length-1; i++){ resultstr += "" + result[i]; } return resultstr; } public static void main(String[] args){ Scanner sc = new Scanner(System.in); System.out.println("请输入第一个数:"); String str1 = sc.next(); System.out.println("请输入第二个数:"); String str2 = sc.next(); largenumberOperationMultiply bn = new largenumberOperationMultiply(); //建立类largenumberOperationMultiply的对象bn String output = bn.multiply(str1,str2); //bn对象调用multiply方法对str1和str2进行操做 System.out.println(str1+"与"+str2+"的积为:"+output); } }
来个c版本的数组实现大数乘法
#include<stdio.h> #include<string.h> #include<math.h> #define N 1005 char a[N],b[N]; int s1[N],s2[N],s3[N*N]; int main() { int len1,len2,max,i,j; while(scanf("%s%s",a,b)!=EOF) { memset(s1,0,sizeof(s1)); memset(s2,0,sizeof(s2)); memset(s3,0,sizeof(s3)); len1=strlen(a); len2=strlen(b); max=0; max=len1+len2; for(i=0,j=len1-1;i<len1;i++,j--) s1[i]=a[j]-'0'; for(i=0,j=len2-1;i<len2;i++,j--) s2[i]=b[j]-'0'; for(i=0;i<len1;i++) for(j=0;j<len2;j++) s3[i+j]+=s1[i]*s2[j]; for(i=0;i<max;i++) { if(s3[i]>=10) { s3[i+1]+=s3[i]/10; s3[i]%=10; } } while(s3[max-1]==0) { if(s3[max-1]==0) max--; } for(i=max-1;i>=0;i--) printf("%d",s3[i]); printf("\n"); } return 0; }