大数乘法

模拟法

参考链接

思路

模拟小学学习的列竖式的方式计算大数,
采用先相加,存储到每一列对于的位子,最后再进位的方式简化计算

        9  8
×       2  1
-------------
       (9)(8)  <----1: 98×1的每一位结果 
  (18)(16)     <----2: 98×2的每一位结果 
-------------
  (18)(25)(8)  <---- 这里就是相对位的和,还没有累加进位 

此处先不考虑进位,先相加得18、25、8,存储在结果的相应位子,最后从右往左,若结果大于10,向左边进位

思路简单,朴实,易于实现

代码实现

#include <iostream>
using namespace std;
class Node {
public:
	Node() { 
		length = 0;	//大数的长度
		memset(s, 0, sizeof(s));	
	}
	Node(char*str) {	//用char初始化,方便使用
		int i = 0;
		memset(s, 0, sizeof(s));
		while (str[i] != '\0')	//当不为空时	
		{
			s[i] = str[i] - '0';	//将str的每一位转化为int型存入s数组
			++i;	//由于从左到右,小标越小,幂此越大
		}
		length = i;
	}
	int length;
	int s[2000];

	void bigNumberMultiply(Node num1, Node num2, Node &result) {	//计算函数
		result.length = num1.length + num2.length;	//result为最后的结果,参数引用
		for (int i = 0; i < num1.length; i++)	//两个for循环模拟竖式计算过程
			for (int j = 0; j < num2.length; j++)
				result.s[i + j + 1] += num1.s[i] * num2.s[j];	//注释1

		for (int k = result.length - 1; k > 0; k--)	//注释2
			if (result.s[k] > 10) {
				result.s[k - 1] += result.s[k] / 10;
				result.s[k] %= 10;
			}	
	}
};
char str[2000];
int main() {
	cout << "请输入大数a和b:" << endl;
	cin >> str;
	Node a(str);
	cin >> str;
	Node b(str);
	
	Node result;
	result.bigNumberMultiply(a, b, result);
	for (int i = 0; i < result.length; i++) {
		if (i == 0 && result.s[i] == 0)continue;	//一开始全部初始化为0,防止第一位有0
		cout << result.s[i];
	}
		

}
  • 注释1(代码第26行)
    `见思路中的计算过程,由于下标越小,幂此越大,因此不同于平常计算时从右往左的习惯,这里我们从左往右看,每一趟的左边都要空出i+j个空位,这里之所以i+j又加了1,是为了将s数组的第一位空出来,防止最高位,也就是最左侧那一位的累加结果需要进位的话,result[]数组就没有空间存放了。
  • 注释2(代码第28行)
    改for循环用于进位,由于下标越小,幂此越大,因此从最大下标开始往小的下标进位

分治法

参考链接

思路

将大数X和Y进行拆分,可将XY简化成下图最后一行式子,看起来复杂,实际降低了复杂度
不断拆分,直到只有一位时,可直接进行相乘

#include<cstdio>
#include<cmath>

using namespace std;

#define SIGN(A) ((A > 0) ? 1 : -1)  //判断正负
int divideConquer(int X, int Y, int n) {    //n位长度的X和Y相乘(此处XY长度相同)
    int sign = SIGN(X) * SIGN(Y);   //判断正负
    int x = abs(X);
    int y = abs(Y);
    if (x == 0 || y == 0) {
        return 0;
    }
    else if (n == 1) {  //当只有一位时,停止递归,输出相乘的值
        return sign * x * y;
    }
    else {
        int A = (int)x / pow(10, (int)(n / 2)); //整除取高位
        int B = x - A * pow(10, n / 2);     //x直接减去高位,得出低位
        int C = (int)y / pow(10, (int)(n / 2));
        int D = y - C * pow(10, n / 2);
        //根据公式要求,分别计算出AC、BD、ABDC
        int AC = divideConquer(A, C, n / 2);
        int BD = divideConquer(B, D, n / 2);
        int ABDC = divideConquer((A - B), (D - C), n / 2) + AC + BD;
        return sign * (AC * pow(10, n) + ABDC * pow(10, (int)(n / 2)) + BD);
    }
}

int main() {
    int x, y, n;
    scanf("%d%d%d", &x, &y, &n);
    printf("x 和 y的乘积为:%d", divideConquer(x, y, n));
}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值