(1)加法
算法的基本思路是模拟列竖式进行加减乘除运算。
输入的数据应当以字符串的方式读取,然后将每个字符转换成数字,并保存在一个整型数组中。
我们输入的自然数字,如“123456789”,最高位“1”是在左侧。而我们进行加、减、乘法运算的时候,是需要个位对齐的。因此,一个自然的思路是将个位放在[0],十位放在[1],以此类推。
两个整型数组a[]和b[],将对应位相加的结果保存在c[]中。如有进位则模10取个位,并设进位。
string A, B; // 两个加数
cin >> A >> B; // 读入两个加数
/* 处理输入的数据 */
int m1 = A.length(); // 加数A的实际位数
int m2 = B.length(); // 加数B的实际位数
int n = max(m1, m2) + 1; // 数组长度。因为可能有进位,所以要+1
int a[n] = {0}; // 加数a,以整型数组表示
int b[n] = {0}; // 加数b,以整型数组表示 保证了相同位数,不同的用0补齐
int c[n] = {0}; // 和c,以整型数组表示
// 将字符型数组转换成“逆序”的整型数组,最低位在左侧,最高位在右侧
// 如:输入的2019,在数组中则是9102。这样个位从下标[0]对齐,方便做运算
for(int i = 0; i < m1; i++)
{
a[i] = A[m1-1-i] - '0'; // 当a[0]时,A[m1-1]
}
for(int i = 0; i < m2; i++)
{
b[i] = B[m2-1-i] - '0';
}
/* 算法 */
// 将a[]与b[]相加,和放在c[]
int x = 0; // 进位
for(int i = 0; i < n; i++)
{
c[i] = a[i] + b[i] + x;
x = c[i]/10; // 更新进位
c[i] %= 10;
}
int j = n-1;
while(c[j]==0 && j > 0) // 前导0不输出
{
j--; // 极限情况:c[]全为0,则最后j=0
}
for(int i = j; i >=0 ; i--) // 逆序输出
{
cout << c[i];
}
cout << endl;
(2)减法
总体思路是模拟竖式做减法的步骤。
被减数可能小于减数,则结果为负数。只要在输入之后,对字符串进行比较,即可得出谁大谁小。我们需要一个标志位来记录正负。然后统一用较大的数减较小的数。
个位对齐。
可能出现借位。
string A, B; // A被减数,B减数
cin >> A >> B; // 读入两个数
/* 处理数据 */
bool isNegative = false; // true,负数;false,正数
int m1 = A.length(); // 数A的实际位数
int m2 = B.length(); // 数B的实际位数
if(m1 < m2 || (m1 == m2 && A < B)) // 如果 A < B
{
isNegative = true; // 结果是负数
swap(A, B); // 让 A 是被减数,B 是减数
swap(m1, m2);
}
int n = max(m1, m2);
int a[n] = {0}; // 被减数a,以整型数组表示
int b[n] = {0}; // 减数b,以整型数组表示
int c[n] = {0}; // 差c,以整型数组表示
// 将字符型数组转换成“逆序”的整型数组,最低位在左侧,最高位在右侧
// 这样个位从下标[0]对齐,方便做运算
for(int i = 0; i < m1; i++)
{
a[i] = A[m1-1-i] - '0';
}
for(int i = 0; i < m2; i++)
{
b[i] = B[m2-1-i] - '0';
}
/* 算法 */
// a[] - b[],结果 c[]
for(int i = 0; i < n ; i++)
{
if(a[i] < b[i]) // 需要借位
{
a[i] += 10; // 借位
a[i+1]--; // 上一位减1
}
c[i] = a[i] - b[i];
}
/* 输出 */
if(isNegative)
{
cout << "-";
}
int j = n-1;
while(c[j]==0 && j > 0) // 前导0不输出
{
j--; // 极限情况:c[]全为0,则最后j=0
}
for(int i = j; i >=0 ; i--) // 逆序输出
{
cout << c[i];
}
cout << endl;
(3)乘法
高精度乘法的要点如下:
依然是模拟竖式乘法的过程。
个位对齐。
AAA乘BBB,是将AAA与每一个B相乘,得数需错一位相加。双层循环实现乘法,一个简单的小技巧即可实现错位相加。
需要一个变量保存进位值。
string A, B; // 两个乘数
cin >> A >> B; // 读入两个数
/* 处理数据 */
int m1 = A.length(); // 数A的实际位数
int m2 = B.length(); // 数B的实际位数
int n = max(m1, m2)*2; // 乘积的最大位数
int a[m1] = {0}; // 乘数a,以整型数组表示
int b[m2] = {0}; // 乘数b,以整型数组表示
int c[n] = {0}; // 乘积c,以整型数组表示
// 将字符型数组转换成“逆序”的整型数组,最低位在左侧,最高位在右侧
// 这样个位从下标[0]对齐,方便做运算
for(int i = 0; i < m1; i++)
{
a[i] = A[m1-1-i] - '0';
}
for(int i = 0; i < m2; i++)
{
b[i] = B[m2-1-i] - '0';
}
/* 算法 */
// a[] 乘 b[] 得 c[]
int x = 0; // 进位
for(int j = 0; j < m2 ; j++) // 循环 b[]
{
x = 0;
for(int i = 0; i < m1; i++) // 循环 a[],每一个数顺序乘 b[j]
{
c[i+j] += a[i]*b[j] + x; // c[i+j] 完美实现错位相加
x = c[i+j]/10;
c[i+j]%=10;
}
c[m1+j] = x; // 可能有进位
}
int j = n-1;
while(c[j]==0 && j > 0) // 前导0不输出
{
j--; // 极限情况:c[]全为0,则最后j=0
}
for(int i = j; i >=0 ; i--) // 逆序输出
{
cout << c[i];
}
cout << endl;
(4)除法
高精度除法,首先第一类,被除数是一个高精度数,而除数是一个有限精度的数(比如int或long long都可以)。这种相对简单一些。
要点如下:
模拟竖式除法。
最高位对齐。因此,a[0]现在是最高位。
对于AAAA除以B来说,从最高位开始依次除以B即可。所得的商即是对应位的商,余数乘10累积到下一次运算。
string A; // 被除数
cin >> A; // 读入被除数
int b; // 除数
cin >> b;
/* 处理数据 */
int n = A.length(); // 数A的实际位数
int a[n] = {0}; // 被除数a,以整型数组表示
int c[n] = {0}; // 商c,以整型数组表示
// 将字符串转成整型数组,a[0]是最高位
for(int i = 0; i < n; i++)
{
a[i] = A[i] - '0';
}
/* 算法 */
int x = 0; // 余数
for(int i = 0; i < n ; i++)
{
x = 10*x + a[i];
c[i] = x / b;
x %= b;
}
int j = 0;
while(c[j]==0 && j < n-1) // 前导0不输出
{
j++; // 极限情况c[]全为0,则j最后等于n-1
}
for(int i = j; i < n ; i++) // 正序输出
{
cout << c[i];
}
cout << endl;
if(x)
{
cout << x << endl; // 余数
}
来源:CSDN
作者:henulmh
链接:https://blog.csdn.net/henulmh/article/details/103958072