1. 大整数 * 小整数
大整数 * 小整数的算法与我们平时计算乘法不完全相同。他是用小整数这个整体与大整数的每一位相乘,将结果保存到一个变量,例如 t 中,然后将 t % 10 即可得到结果的一位。然后将 t / 10 就可以得到进位,这里的进位不同于加法,加法的进位只可能是 1 ,而乘法的进位是多种多样的。当大整数的最高位乘上这个小整数后如果有进位,则将进位由低位到高位依次push_back到保存结果的数组中即可。
分析到这里我们也能够理解为啥是大整数 * 小整数,而不是大整数 * 大整数了:这里的算法是将一个整数看作整体,依次去和另一个整数的每一位相乘,然后将得到的结果保存在一个中间变量中,如果这是一个大整数,他去和另一个大整数相乘时,结果可能溢出,即超过中间变量的存储范围。
vector<int> mul(vector<int>& A, int b)
{
vector<int> C;
int t = 0;
//这里将每一位的乘法和最高位产生进位的循环合并到一起了
for (int i = 0; i < A.size()|| t; i++)
{
if (i < A.size())
{
t += A[i] * b;
}
C.push_back(t % 10);
t /= 10;
}
return C;
}
void test03()
{
string a;
int b;
cout << "请输入两个整数,以回车键结束" << endl;
cin >> a >> b;
vector<int> A;
for (int i = a.size() - 1; i >= 0; i--)
A.push_back(a[i] - '0');
vector<int> C = mul(A, b);
for (int i = C.size() - 1; i >= 0; i--)
{
cout << C[i];
}
cout << endl;
}
int main()
{
//大整数的乘法
test03();
system("pause");
return 0;
}
2. 大整数 / 小整数
该算法要求我们计算出最终的商和余数,同理如果是大整数 / 大整数的话,最终的余数可能无法用简单的数据类型来存储,所以这里我们计算的是大整数 / 小整数。
该算法和人类计算除法是相似的,只是人类会根据被除数的位数,直接判断出可能有结果的位,显然计算机是无法直接这么做的,只能对每一位进行计算。
有一点与其他三种大整数的算法不同:除法是从最高位开始算的,这意味着,我们将结果保存到数组中时,下标为0的位置是存的最高位。显然,仅针对除法来说这是完全没有什么大的问题的,但是,在实际运算过程中,并不可能只进行除法运算,所以需要将大整数的存储方式统一。在完成计算后将数组逆序即可。
讲了这么多,除法该怎么算呢?从大整数的最高位开始,将每一位去和小整数(除数)相除得到的结果就是该位最终的结果,然后再将该位与小整数(除数)取模,在对下一位进行计算时,将取模得到的结果乘以 10 ,在加上这一位的数字。然后重复上述操作,直到算完大整数的每一位。如果说最后一位对小整数取模不为 0 ,得到的结果便是最终结果的余数啦。
//参数r用来接收余数
vector<int> div(vector<int>& A, int b, int& r)
{
vector<int> C;
r = 0;
//不同于前三种,这是从最高位开始算
for (int i = A.size() - 1; i >= 0; i--)
{
r = A[i] + r * 10;
C.push_back(r / b);
r = r % b;
}
//逆置数组
reverse(C.begin(), C.end());
//去掉前导0
while (C.size() > 1 && C.back() == 0)
{
C.pop_back();
}
return C;
}
void test04()
{
string a;
int b;
cout << "请输入两个整数,以回车键结束" << endl;
cin >> a >> b;
vector<int> A;
for (int i = a.size() - 1; i >= 0; i--)
A.push_back(a[i] - '0');
int r;
vector<int> C = div(A, b, r);
cout << "结果:";
for (int i = C.size() - 1; i >= 0;i--)
{
cout << C[i];
}
cout << endl;
//输出余数
cout << "余数:" << r << endl;
}
int main()
{
//大整数的除法
test04();
system("pause");
return 0;
}