JAVA大数相乘实现方法

转载自:【方法1】【方法2】

public class DaShuXiangCheng {
	
	//*********************** 【方法1】 Start **************************************
	
	// 规模只要在这个范围内可以直接计算(整型数值满足)
		private final static int SIZE = 4;
	 
		// 其中,len为X、Y的长度最大值
		private static String bigIntMultiply(String X, String Y, int len) {
			String str = "";
	 
			if (len <= SIZE) { // 少于4位数,可直接计算
				return "" + (Integer.parseInt(X) * Integer.parseInt(Y));
			}
	 
			if (X.length() != Y.length()) { // 长度不同,调用formatNumber方法,补齐X、Y,使之长度相同
				X = formatNumber(X, len);
				Y = formatNumber(Y, len);
			}
	 
			// 将X、Y分别对半分成两部分
			int len1 = len / 2;
			int len2 = len - len1;
			String A = X.substring(0, len1);
			String B = X.substring(len1);
			String C = Y.substring(0, len1);
			String D = Y.substring(len1);
	 
			// 乘法法则,分块处理
			int lenM = Math.max(len1, len2);
			String AC = bigIntMultiply(A, C, len1);
			String AD = bigIntMultiply(A, D, lenM);
			String BC = bigIntMultiply(B, C, lenM);
			String BD = bigIntMultiply(B, D, len2);
	 
			
			// 注意处理进位的方法,巧妙地运用了字符串的拼接方面
			// 【1】 处理BD,得到原位及进位
			String[] sBD = dealString(BD, len2);
			
			// 【2】 处理AD + BC的和
			String ADBC = add(AD, BC);
			
			// 【3】 加上BD的进位
			if (!"0".equals(sBD[1])) {
				ADBC = add(ADBC, sBD[1]);
				
			}
			// 【4】 得到ADBC的进位
			String[] sADBC = dealString(ADBC, lenM);
	 
			// 【5】 AC加上ADBC的进位
			AC = add(AC, sADBC[1]);
			
			// 【6】 最终结果
			str = AC + sADBC[0] + sBD[0];
			
			return str;
		}
	 
		// 两个数字串按位加
		private static String add(String ad, String bc) {
			// 返回的结果
			String str = "";
	 
			// 两字符串长度要相同
			int lenM = Math.max(ad.length(), bc.length());
			ad = formatNumber(ad, lenM);
			bc = formatNumber(bc, lenM);
	 
			// 按位加,进位存储在flag中
			int flag = 0;
			// 按序从后往前按位求和
			for (int i = lenM - 1; i >= 0; i--) {
				int t = flag + Integer.parseInt(ad.substring(i, i + 1))
						+ Integer.parseInt(bc.substring(i, i + 1));
				// 结果超过9,则进位当前位,保留个位数
				if (t > 9) {
					flag = 1;
					t = t - 10;
				} else {
					flag = 0;
				}
				// 拼接结果字符串
				str = "" + t + str;
			}
			if (flag != 0) {
				str = "" + flag + str;
			}
			return str;
		}
	 
		// 处理数字串,分离出进位,String数组第一个为原位数字,第二个为进位
		private static String[] dealString(String ac, int lenn) {
			String[] str = { ac, "0" };
	 
			if (lenn < ac.length()) {
				int t = ac.length() - lenn;
				str[0] = ac.substring(t);
				str[1] = ac.substring(0, t);
				// System.out.println("+++++++++");
				// System.out.println(str[0]);
				// System.out.println(str[1]);
				// System.out.println(t);
			} else {
				// 保证结果length与lenn一致,少于则高位补0
				String result = str[0];
				for (int i = result.length(); i < lenn; i++) {
					result = "0" + result;
				}
				str[0] = result;
			}
			return str;
		}
	 
		// 格式化操作的数字字符串,高位补零
		private static String formatNumber(String x, int len) {
			while (len > x.length()) {
				x = "0" + x;
			}
			return x;
		}
		//*********************** 【方法1】 End **************************************
		
		
		//*********************** 【方法2】 Start **************************************
		public static String multiply2(String num1, String num2){
	        //把字符串转换成char数组
	        char chars1[] = num1.toCharArray();
	        char chars2[] = num2.toCharArray();

	        //声明存放结果和两个乘积的容器
	        int result[] = new int[chars1.length + chars2.length];
	        int n1[] = new int[chars1.length];
	        int n2[] = new int[chars2.length];

	        //把char转换成int数组,为什么要减去一个'0'呢?因为要减去0的ascii码得到的就是实际的数字
	        for(int i = 0; i < chars1.length;i++)
	            n1[i] = chars1[i]-'0';
	        for(int i = 0; i < chars2.length;i++)
	            n2[i] = chars2[i]-'0';

	        //逐个相乘,因为你会发现。AB*CD = AC(BC+AD)BD , 然后进位。
	        for(int i =0 ; i < chars1.length; i++){
	            for(int j =0; j < chars2.length; j++){
	                result[i+j]+=n1[i]*n2[j];
	            }
	        }

	        //满10进位,从后往前满十进位
	        for(int i =result.length-1; i > 0 ;i--){
	            result[i-1] += result[i] / 10;
	            result[i] = result[i] % 10;
	        }

	        //转成string并返回
	        String resultStr = "";
	        for(int i = 0; i < result.length-1; i++){
	            resultStr+=""+result[i];
	        }
	        return resultStr;
	    }
		//*********************** 【方法2】 End **************************************
		
		public static void main(String[] args) {
			//String x = "38202212122222222222222222222222221111111111111111111111111111111111111111111111111114444444";
			//String y = "42204412121222222222222222222222225555555555555555555222222246666678921345643444657683512121";
			//System.out.println("bigIntMultiply("+x+", "+y+", "+Math.max(x.length(), y.length())+")");
			String x  = "";
			for(int i=1;i<100;i++){
				x += i;
			}
			String y = "";
			for(int i=99;i>0;i--){
				y += i;
			}
			System.out.println("x = "+x);
			System.out.println("y = "+y);
			
			Long fun1_dateStart = new Date().getTime();
			String result = bigIntMultiply(x, y, Math.max(x.length(), y.length()));
			Long fun1_dateEnd = new Date().getTime();
			System.out.println("方法1结果为  : "+result+"。 \r\n 用时 : "+(fun1_dateEnd - fun1_dateStart));
			//System.out.println(x+" * "+y+" = "+result);
			Long fun2_dateStart = new Date().getTime();
			String result2 = multiply2(x, y);
			Long fun2_dateEnd = new Date().getTime();
			System.out.println("方法2结果为  : "+result2+"。 \r\n 用时 : "+(fun2_dateEnd - fun2_dateStart));
			//System.out.println("multiply2("+x+", "+y+") = "+result2);
		}

}

结果

猜你喜欢

转载自blog.csdn.net/yhzhaohy/article/details/84792355