高精度乘法
高精度乘法
给定两个非负整数(不含前导 0)A 和 B,请你计算 A×B 的值。
所用方法和基本原理
该代码采用一种简化的乘法方式来实现大数乘法(大数x小数),基本原理如下:
- 数位拆分与转换:
- 对于字符串A,将其每一位数字拆分出来存储到数组mulA中,从字符串末尾开始处理,方便后续按位运算。
- 对于字符串b,将其转换为一个整数mulb。通过遍历字符串b,利用Math.pow(10, j) * (b.charAt(i) - '0')的方式,将每一位数字乘以对应的权值并累加,得到b对应的整数值。 - 模拟乘法运算:
- 创建一个长度为ALen + 1的结果数组res来存储乘法结果,最后一位可能是多位数,而前面都是单位数。
- 初始化一个变量t用于存储进位。
- 遍历数组mulA,将每一位与mulb相乘,并加上之前的进位t,得到当前位的和iSum。将iSum对 10 取余得到当前位的数字存入res数组,iSum除以 10 得到新的进位t。 - 处理结果:
- 从结果数组的高位开始(即ALen位置),跳过前导 0,找到第一个非零元素的位置startIdx。
- 将从startIdx开始到数组开头的元素依次添加到StringBuffer中,最后转换为字符串返回。
代码及注释
public class BigNumberMultiplication {
// 实现两个非负整数字符串的乘法
public static String mul(String A, String b) {
int ALen = A.length();
int bLen = b.length();
// 创建数组mulA用于存储字符串A按位拆分后的数字
int[] mulA = new int[ALen];
int mulb = 0;
// 将字符串A按位拆分并存入mulA数组
for (int i = ALen - 1, j = 0; i >= 0; i--, j++) {
mulA[j] = A.charAt(i) - '0';
}
// 将字符串b转换为整数mulb
for (int i = bLen - 1, j = 0; i >= 0; i--, j++) {
mulb += Math.pow(10, j) * (b.charAt(i) - '0');
}
// 创建结果数组res,长度为ALen + 1
int[] res = new int[ALen + 1];
int t = 0;
// 模拟乘法运算,逐位相乘并处理进位
for (int i = 0; i < ALen; i++) {
int iSum = mulA[i] * mulb + t; // 当前这一位的和
res[i] = iSum % 10; // 每一位上的数字
t = iSum / 10; // 进位
}
res[ALen] = t; // 最后一位
// 找到结果数组中第一个非零元素的位置,跳过前导0
int startIdx = ALen;
while (res[startIdx] == 0) {
startIdx--;
if (startIdx < 0) {
return "0";
}
}
// 创建StringBuffer用于构建结果字符串
StringBuffer resStr = new StringBuffer();
// 将结果数组从有效位开始添加到StringBuffer中
for (int i = startIdx; i >= 0; i--) {
resStr.append(res[i]);
}
return resStr.toString();
}
}
举例说明
假设 A = "123",b = "45"。
- 数位拆分与转换:
-ALen = 3,bLen = 2。
-mulA = [3, 2, 1]。
-mulb = 5 * Math.pow(10, 0) + 4 * Math.pow(10, 1) = 45。 - 模拟乘法运算:
- 第一次循环:i = 0,iSum = 3 * 45 + 0 = 135,res[0] = 135 % 10 = 5,t = 135 / 10 = 13。
- 第二次循环:i = 1,iSum = 2 * 45 + 13 = 103,res[1] = 103 % 10 = 3,t = 103 / 10 = 10。
- 第三次循环:i = 2,iSum = 1 * 45 + 10 = 55,res[2] = 55 % 10 = 5,t = 55 / 10 = 5。
- 此时res = [5, 3, 5, 5]。 - 处理结果:
-startIdx = 3,从startIdx开始添加元素到resStr,得到"5535"。
方法的优劣
- 时间复杂度:
- 对于字符串A的拆分时间复杂度为 (O(m)),其中m是A的长度;对于字符串b转换为整数的时间复杂度为 (O(n)),其中n是b的长度;模拟乘法运算的时间复杂度为 (O(m))。总体时间复杂度为 (O(m + n)),这里假设 (m \geq n)。 - 空间复杂度:
- 创建了一个长度为ALen + 1的数组res和长度为ALen的数组mulA,空间复杂度为 (O(m)),这里 (m) 是A的长度。同时在计算mulb时,可能会涉及到与n相关的临时空间,但总体空间复杂度主要由数组决定,为 (O(m))。
优点:
- 实现相对简单,对于较小规模的大数乘法能够较为直观地计算出结果。
- 代码逻辑较为清晰,容易理解。
缺点:
- 当 b 是一个非常大的数时,将其转换为整数可能会导致整数溢出,限制了该方法处理大数的能力。
- 空间复杂度相对较高,需要额外的数组来存储中间结果。对于非常大的数,内存消耗较大。
- 从算法效率上看,这种简单的乘法方式在处理大规模数据时,时间复杂度不是最优的,存在更高效的大数乘法算法,如 Karatsuba 算法等。

浙公网安备 33010602011771号