一、高精度乘法(高精乘低精)
与高精度加法与减法类似,高精度的乘法,我们依然是按照“竖式运算”的原理进行计算。例如:
#include<bits/stdc++.h>
using namespace std;
string s1;
int b,flaga,flagb;
int a[100005];
int main()
{
cin>>s1>>b;
if ('-'==s1[0])
{
flaga = true;
s1.erase(s1.begin());//删除负号
}
if(b<0)
{
flagb = true;
b=-b;
}
if( flaga !=flagb ) //负负得正,正负得负,负正得负,正正得正
printf("-");
int len=s1.size();
for(int i=0;i<len/2;i++) //将字符串翻转
swap(s1[i],s1[len-1-i]);
int jw=0;
for(int i=0;i<len;i++)
{
a[i]+=(s1[i]-'0')*b+jw;
jw=a[i]/10;
a[i]%=10;
}
if(jw>0)
{
a[len]=jw;
len++;
}
int t=0;
for(int i=len-1;i>=0;i--)
cout<<a[i];
return 0;
}
二、高精度乘法(高精乘高精)
与高精度加法与减法类似,高精度的乘法,我们依然是按照“竖式运算”的原理进行计算。例如:
我们假设用数组A存储被乘数856的每一位,具体来说就是A0存储个位6,A1存储十位5,A2存储百位8;使用数组B存储乘数25,存储结构与数组A类似;使用数组C存储对应的乘积21400,存储结构与数组A类似,那么结果则如表格所示:
首先,我们不难推测
C0 = C’0 = A0 × B0;
C1 = C’1 + C”1 = A1 × B0 + B1 × A0 + 进位
C2 = C’2 + C”2 = A2 × B0 + B1 × A1 + 进位
C3 = C’3 + C”3 = A3 × B0 + B1 × A2 + 进位
...
根据规律我们可以总结特点:
- a[i] × b[j] 的答案应该累加到 c[i+j] 的位置;
- 累加总结果为:c[i+j] += a[i] × b[j] + 进位
- 带入下一位累加的进位为c[i+j]/10,本位实际数为c[i+j]%=10
具体实现思路:
- 输入两个字符串,先将其进行预处理(将字符串中的数翻转后存入数组中);
- 先判断两个字符串所代表的数的正负情况,提前做好符号标记;
- 使用双重循环,分别求出a[i] × b[j] 的结果并累计到 c[i+j] 中;
- 进行下一位累加的进位计算并加起来,同时求出本位的实际数;
- 删除前导零;
- 求解完毕后,将乘积数组c反向输出。
思考:为什么高精度乘法不像之前的高精度加法与减法一样,之前从后面往前开始计算,而是要先进行预处理,将其翻转后再计算?
具体代码:
- 定义数组:
int MAXN = 1e5+4; //根据题目的最大值。+4为了防止A+B出现进位
string s1;//存储字符串
string s2;//存储字符串
int a[MAXN] = {};//存储加数A
int b[MAXN] = {};//存储加数B
int c[2*MAXN] = {};//存储乘积
- 读入数据,考虑处理正负数相乘的形式:
cin>>s1>>s2;//读入字符串
//处理负数
bool flaga = false;//乘数a的符号
if ('-'==s1[0]) {
flaga = true;
s1.erase(s1.begin());//删除负号
}
bool flagb = false;//乘数b的符号
if ('-'==s2[0]) {
flagb = true;
s2.erase(s2.begin());//删除负号
}
//处理输出的负号
if ((flaga != flagb) {
printf("-");
}
//处理乘数1
int lena = s1.size();
for (int i=0; i<lena; i++) {
a[lena-i-1]=s1[i]-'0';
}
//处理乘数2
int lenb = s2.size();
for (int i=0; i<lenb; i++) {
b[lenb-i-1]=s2[i]-'0';
}
- 模拟竖式乘法运算
int jw;//上一轮计算进位
for (int i=0; i<lena; i++) {
jw=0;
for (int j=0; j<lenb; j++) {
//交叉乘积
c[i+j] = a[i]*b[j]+jw+c[i+j];//当前乘积+上次乘积进位+原数
jw = c[i+j]/10;//处理进位
c[i+j] %= 10;
}
c[i+lenb]=jw;//进位设置
}
- 删除前导零
int lenc=lena+lenb;
for (int i=lenc-1; i>=0; i--) {
//因为我们是从索引 0 开始,所以最高位是保存在 len-1
if (0==c[i] && lenc>1) {
//注意要有 lenc>1 这个条件。考虑特殊情况,加法结果为 00,我们实际要输出 0。
lenc--;
}
else {
//第一个不是零的最高位,结束删除
break;
}
}
- 输出计算结果
for (int i=lenc-1; i>=0; i--) {
printf("%d", c[i]);
}
printf("\n");