高进度加法

a + b 自然是个很简单的问题,但若 a 和 b 都能达到两百位的话,连 unsigned long long 都存不了,这是就要用到高精度加法。

 

具体原理就是让电脑模拟列竖式加法。

 

首先我们用数组存这两个数。为了方便读入,我们采用字符串读入,然后将其转化成数字存进数组中。存进数组的时候要倒着存入,为什么呢?这样的话就能保证两个数的每一位都对齐了,为接下来的模拟列竖式提供了很大的便利。

 

模拟列竖式其实也不必多说,写法也不少。其实关键在于进位的问题,一种写法是先进位,在把这一位的两数相加;一种是先相加,然后为下一位进位。这两种写法是一样的,喜欢哪一种,就看个人习惯吧。

 

 

那么先说一下第一种方法。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
const int maxn = 1e5 + 5;
char a1[maxn], b1[maxn];
int a[maxn], b[maxn], c[maxn]; 
int jinwei = 0;
int main()
{
    scanf("%s%s", a1, b1);
    int la = strlen(a1), lb = strlen(b1);
    for(int i = 0; i < la; ++i) a[la - 1 - i] = a1[i] - '0';    //倒着存入 
    for(int i = 0; i < lb; ++i) b[lb - 1 - i] = b1[i] - '0';
    for(int i = 0; i < max(la, lb); ++i)        //当然要加到位数多的数了 
    {
        c[i] = c[i] + jinwei + a[i] + b[i];        
        jinwei = c[i] / 10;
        c[i] %= 10;
    }
    int x = max(la, lb);
    if(jinwei > 0) c[x] += jinwei;        //处理最高位的进位 
    while(x > 0 && c[x] == 0) x--;        //删除前导0,比如 0000 + 00 = 0,而不是 0000 
    for(int i = x; i >= 0; --i) printf("%d", c[i]);        //倒着输出 
    printf("\n");
    return 0;
}

仔细瞅一瞅,这个代码其实还可以优化一下:

1.不用开 c 数组,在 a 数组上改动即可。

2.这其实不算什么优化,只不过代码看得更简洁:考虑一下最高位进位的问题,若最高位可以进位,那新的一位一定是超出了 max(la, lb),因此会跳出循环,所以我们的写法就是在循环外面单独处理。但其实我们完全可以把它放到循环里面,只要把最高位的下一位看成一位,而且可以确定的是,这一位一定不会再进位了(因为没有数,默认是0,加任何小于10的数都不会进位),这么一改,我们也就不用考虑最高位进位的事了。

发一下优化后的

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<cstring>
 6 using namespace std;
 7 const int maxn = 1e5 + 5;
 8 char a1[maxn], b1[maxn];
 9 int a[maxn], b[maxn]; 
10 int jinwei = 0;
11 int main()
12 {
13     scanf("%s%s", a1, b1);
14     int la = strlen(a1), lb = strlen(b1);
15     for(int i = 0; i < la; ++i) a[la - 1 - i] = a1[i] - '0';     
16     for(int i = 0; i < lb; ++i) b[lb - 1 - i] = b1[i] - '0';
17     for(int i = 0; i <= max(la, lb); ++i)    //注意加了个 '=',默认加到最高位的下一位 
18     {
19         a[i] = a[i] +jinwei + b[i];    
20         jinwei = a[i] / 10;
21         a[i] %= 10;
22     }
23     int x = max(la, lb);        //不用考虑最高位进位的事了 
24     while(x > 0 && a[x] == 0) x--;        //删除前导0
25     for(int i = x; i >= 0; --i) printf("%d", a[i]);    
26     printf("\n");
27     return 0;
28 }

 

 

那就顺便说一下第二种方法吧。

其实差不多,只不过不用开一个变量记录进位了,因为每一次考虑的是给下一位进位,只要 c[i + 1] 处理一下就行了,除此之外,也就没什么差别。

就直接发优化后的代码了

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<cstring>
 6 using namespace std;
 7 const int maxn = 1e5 + 5;
 8 char a1[maxn], b1[maxn];
 9 int a[maxn], b[maxn]; 
10 int main()
11 {
12     scanf("%s%s", a1, b1);
13     int la = strlen(a1), lb = strlen(b1);
14     for(int i = 0; i < la; ++i) a[la - 1 - i] = a1[i] - '0';     
15     for(int i = 0; i < lb; ++i) b[lb - 1 - i] = b1[i] - '0';
16     for(int i = 0; i <= max(la, lb); ++i)    
17     {
18         a[i] += b[i];    
19         a[i + 1] += a[i] / 10;         //进位 
20         a[i] %= 10;
21     }
22     int x = max(la, lb);        
23     while(x > 0 && a[x] == 0) x--;    
24     for(int i = x; i >= 0; --i) printf("%d", a[i]);    
25     printf("\n");
26     return 0;
27 }

 

 

总结一下,高进度只不过是一个模拟,只要耐心仔细一点,把进位搞明白,就没什么不好写的了。

转载于:https://www.cnblogs.com/mrclr/p/8520005.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值