高精度计算需要注意的几个问题:
1.用字符串的读入方式,再按字符分别转成数字2.不能用数值型的读入方式二、计算过程中考虑进位和借位问题(先不急于处理,在计算结束时处理)1.数组第i元素>=10(或<0)需要考虑2.从上位增或减1,本位减或加10三、输出时注意跳过高位多余的0四、数组需要稍微大一些,避免运算时溢出问题描述
求两个不超过200位的非负整数的积。
输入数据有两行,每行是一个不超过200位的非负整数,没有多余的前导0。
输出要求
一行,即相乘后的结果。结果里不能有多余的前导0,即如果结果是342,那么就不能输出为0342。
输入样例
12345678900
98765432100
输出样例
1219326311126352690000
解题思路
1.用unsigned an1[200]和unsigned an2[200]分别存放两个乘数,用aResult[400]来存放积。计算的中间结果也都存在aResult中。aResult长度取400是因为两个200位的数相乘,积最多会有400位。an1[0], an2[0], aResult[0]都表示个位。
2.一个数的第i位和另一个数的第j位相乘所得的数,一定是要累加到结果的第i+j位上。这里i, j都是从右往左, 从0开始数。
3.计算的过程基本上和小学生列竖式做乘法相同。为编程 方便,并不急于处理进位,而将进位问题留待最后统一处理。
#include <iostream>
#include <cstring>
using namespace std;
#define MAX 200
int Multiply(int *a1, int *a2, int *result, int nLen1, int nLen2)
{
//大整数乘法
int i, j;
int nHighestPos = 0;
for(j = 0; j <= nLen2 - 1; ++j)
{
for(i = 0; i <= nLen1 - 1; ++i)
{
result[i + j] += a1[i] * a2[j];//注意是+=才可以把进位相加
}
}
for(int k = 0; k <= nLen1 + nLen2; ++k)
{
if(result[k] >= 10)
{
result[k + 1] += result[k] / 10;
result[k] %= 10;
}
if(result[k])
{
nHighestPos = k;
}
}
return nHighestPos;
}
int main()
{
while(1)
{
char *s1 = new char[MAX + 10]();
char *s2 = new char[MAX + 10]();
int *a1 = new int[MAX + 10]();
int *a2 = new int[MAX + 10]();
int *result = new int[MAX + MAX + 10]();
cin >> s1;
cin >> s2;
int nLen1 = strlen(s1);
for(int i = nLen1 - 1, j = 0; 0 <= i; --i)
{
a1[j++] = s1[i] - '0';
}
int nLen2 = strlen(s2);
for(int i = nLen2 - 1, j = 0; 0 <= i; --i)
{
a2[j++] = s2[i] - '0';
}
int Flag = Multiply(a1, a2, result, nLen1, nLen2);
//进位处理
bool bStartOutput = false;//此变量用于跳过多余的0
for(int k = Flag; 0 <= k; --k)
{
if(bStartOutput)//遇到多余的0都跳过,否则输出
{
cout << result[k];
}else if(result[k])
{
bStartOutput = true;//碰到第一个非零值,则表明多余的0已都跳过
cout << result[k];
}
}
if(!bStartOutput)
{
cout << 0;
}
cout << endl;
delete [] s1;
delete [] s2;
delete [] a1;
delete [] a2;
delete [] result;
}
return 0;
}