高精度计算

(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;
     //其实也可以不要进位,直接在当前位更新下一位
     //c[i]=a[i]+b[i];
     //c[i+1]=c[i]/10;
     //c[i]%=10;
     //还有就是如果题目给出的不是10进制的加法,而是n进制,则在运用高精度时
     //把/10,%10改为/n,%n即可。
     //而且也可以不用新开这个c[]数组,还可以直接将和存在a[]数组中
}
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]刚好实现
            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; // 余数
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

henulmh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值