大整数相乘,输入小数也可以,其原理是分块相乘,将输入的数对半分成高位和低位,使大整数划分为小数,然后将小数相乘获取原高地位的大数
可以通过规律:大整数1*大整数2=高位1*高位2+中位进位+中位(高位1乘低位2+低位1乘高位2)+低位进位+低位1*低位2
拼接大整数
java代码如下:
// 分块相乘
public String bigMul(String num1, String num2, int len) {
if (null == num1 || "".equals(num1) || null == num2 || "" == num2) {
return "0";
}
int pointNum = 0;// 小数点移位距离
// 如果是小数
if (num1.contains(".")) {
pointNum += num1.length()-num1.indexOf(".")-1;
String h = num1.substring(0, num1.indexOf("."));
String l = num1.substring(num1.indexOf(".") + 1);
num1 = h + l;
}
if (num2.contains(".")) {
pointNum += num2.length()-num2.indexOf(".")-1;
String h = num2.substring(0, num2.indexOf("."));
String l = num2.substring(num2.indexOf(".") + 1);
num2 = h + l;
}
// 取得最长的数
// 将长度调整相同
num1 = formatNumber(num1, len);
num2 = formatNumber(num2, len);
// 如果长度小于4,则直接乘
if (num1.length() <= 4) {
String result = String.valueOf(Integer.valueOf(num1)
* Integer.valueOf(num2));
String setPoint = setPoint(pointNum, result);
return setPoint;
}
// 如果长度大于四,将两个数分成高低位
int halfLen = len / 2;
int halfLen2 = len - halfLen;
String num1H = num1.substring(0, halfLen);
String num1L = num1.substring(halfLen);
String num2H = num2.substring(0, halfLen);
String num2L = num2.substring(halfLen);
int maxLen = Math.max(halfLen, halfLen2);
// 高位*高位
String H1H2 = bigMul(num1H, num2H, halfLen);
// 高位*低位
String H1L2 = bigMul(num1H, num2L, maxLen);
// 低位乘高位
String L1H2 = bigMul(num1L, num2H, maxLen);
// 低位*低位
String L1L2 = bigMul(num1L, num2L, halfLen2);
// 从低位开始,先取低位的进位
String[] carryL = getCarry(L1L2, halfLen2);
// 将中间两位相加
String mid = additionMid(H1L2, L1H2);
String carry = carryL[0];
if (carry != null && !carry.equals("0")) {
mid = additionMid(mid, carry);
}
// 首位加上中位进位再取进位
String[] carryMid = getCarry(mid, maxLen);
String carryM = carryMid[0];
String high = "";
high = additionMid(H1H2, carryM);
// 将三者叠加即可
String result = high + carryMid[1] + carryL[1];
result = setPoint(pointNum, result);
return result;
}
private String setPoint(int pointNum, String result) {
// 设置小数点
if (pointNum > 0) {
String sRes = "." + result.substring(result.length() - pointNum);
String hRes = result.substring(0, result.length() - pointNum);
result = hRes + sRes;
}
return result;
}
private String additionMid(String h1l2, String l1h2) {
int carryFlag = 0;
int maxLength = Math.max(h1l2.length(), l1h2.length());
h1l2 = formatNumber(h1l2, maxLength);
l1h2 = formatNumber(l1h2, maxLength);
String numRes = "";
String[] result = { "0", numRes };
for (int i = maxLength - 1; i >= 0; i--) {
int num1 = Integer.parseInt(h1l2.substring(i, i + 1));
int num2 = Integer.parseInt(l1h2.substring(i, i + 1));
int singleAddition = num1 + num2 + carryFlag;
carryFlag = 0;
if (singleAddition >= 10) {
carryFlag = 1;
singleAddition -= 10;
}
numRes = singleAddition + numRes;
}
result[0] = String.valueOf(carryFlag);
result[1] = numRes;
// 如果最高位有进位,则加上去
if (carryFlag != 0) {
numRes = carryFlag + numRes;
}
return numRes;
}
// 0:进位,1:值
private String[] getCarry(String l1l2, int len) {
String carry[] = { "0", l1l2 };
if (l1l2.length() > len) {
// 有进位
int sub = -len + l1l2.length();// 获得多出来的长度
String substring = l1l2.substring(0, sub);// 截取进位长度
String valueString = l1l2.substring(sub);// 截取进位后的长度
carry[0] = substring;
carry[1] = valueString;
} else {
for (int i = l1l2.length(); i < len; i++) {
carry[1] = "0" + carry[1];
}
}
return carry;
}
@Test
public void fun() {
//首数字不能为零
String num1 = "14.4";
String num2 = "1.42";
String bigMul = bigMul(num1, num2,
Math.max(num1.length(), num2.length()));
bigMul = getPruNum(bigMul);
System.out.println(bigMul);
}
private String getPruNum(String bigMul) {
for (int i = 0; i < bigMul.length(); i++) {
String w = bigMul.substring(0, 1);
if (w.equals("0")) {
bigMul = bigMul.substring(1);
} else {
return bigMul;
}
}
return bigMul;
}