高精度加、减及混合

我们知道,减法在本质上其实是加法,就是把数字前的负号当成这个数字的组成部分

那么,如何实现真正的高精度加法呢(即需要考虑负数的情况)?

一步一步来吧!

 

PART1:

    有两个很大的非负整数,大概有10^1000的位数那么大,求和?

    这就是很纯的高精度加法,即不用考虑负数的情况,实现如下:

1 void add(BigNum *x,BigNum *y,BigNum *z){
2     z->len=max(x->len,y->len);
3     for(int i=1;i<=z->len;i++){
4         z->s[i]+=x->s[i]+y->s[i];
5         z->s[i+1]=z->s[i]/10;
6         z->s[i]%=10;
7     }
8     if(z->s[z->len+1]) z->len++;
9 }
纯高精度加法

   

    说明一下,以下部分也一样

    我们开了个结构体BigNum储存大整数的长度、其本身和符号:

1 struct BigNum{
2     int s[maxn],len,f;
3     BigNum(){len=0;f=1;memset(s,0,sizeof(s));}//为重构函数,这样可以在声明变量的时候就把变量初始化 
4 };
BigNum

     x、y为拿来操作的两个大整数,z为结果

     这里用的指针,传给函数的是大整数的地址,可以直接修改对应的大整数,操作起来会比较方便

 

PART2:

      有两个很大的非负整数,大概有10^1000的位数那么大,被减数有可能小于减数,求差?

      这就是所谓的高精减

      因为不保证被减数不小于减数,所以需要多进行一步判z的符号的操作,实现如下:

 1 void subtract(BigNum *x,BigNum *y,BigNum *z){//符号确定后差的值就是大数减小数 
 2     for(int i=1;i<=x->len;i++){
 3          z->s[i]=x->s[i]-y->s[i];
 4         if(z->s[i]<0){
 5             x->s[i+1]--;
 6             z->s[i]+=10;
 7         }
 8     }
 9     int o=x->len;
10     while(o>1&&!z->s[o]) o--;
11     z->len=o;
12 }
13 void sub(BigNum *x,BigNum *y,BigNum *z){//判断差的符号 
14     if(x->len<y->len){
15         z->f=-1;
16         subtract(y,x,z);
17     }
18     else if(x->len==y->len){
19         for(int i=x->len;i>0;i--)
20           if(x->s[i]<y->s[i]){
21               z->f=-1;
22               subtract(y,x,z);
23               return;
24           }
25         subtract(x,y,z);
26     }
27     else subtract(x,y,z);
28 }
高精度减法

 

RART3:

      有两个很大的整数,大概有10^1000的位数那么大,求和?

       这就是我们的目的所在

       其实就是把以上的做法结合起来

       除此之外,开始处理之前还需要再加一步对输入大整数符号的判断,好分配接下来的工作

 

完整代码:

 

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<iostream>
 4 #define maxn 2333
 5 using namespace std;
 6 struct BigNum{
 7     int s[maxn],len,f;
 8     BigNum(){len=0;f=1;memset(s,0,sizeof(s));}//为重构函数,这样可以在声明变量的时候就把变量初始化 
 9 };
10 char ai[maxn],bi[maxn];
11 BigNum a,b,c;
12 void add(BigNum*,BigNum*,BigNum*);
13 void subtract(BigNum*,BigNum*,BigNum*);
14 void sub(BigNum*,BigNum*,BigNum*);
15 void allot(BigNum*,BigNum*,BigNum*);
16 int main(){
17     scanf(" %s %s",ai,bi);
18     a.len=strlen(ai);
19     b.len=strlen(bi);
20     for(int i=a.len-1;i>0;i--) a.s[a.len-i]=ai[i]-'0';
21     for(int i=b.len-1;i>0;i--) b.s[b.len-i]=bi[i]-'0';
22     if(ai[0]=='-'){
23         a.f=-1;a.len--;
24     }
25     else a.s[a.len]=ai[0]-'0';
26     if(bi[0]=='-'){
27         b.f=-1;b.len--;
28     }
29     else b.s[b.len]=bi[0]-'0';
30     allot(&a,&b,&c);
31     if(c.f<0) putchar('-');
32     for(int i=c.len;i>0;i--) printf("%d",c.s[i]); 
33     return 0;
34 }
35 void allot(BigNum *x,BigNum *y,BigNum *z){ //判断所输入大整数需要进行何种计算  
36     if(x->f<0&&y->f<0){
37         z->f=-1;
38         add(x,y,z);
39     }
40     else if(x->f>0&&y->f>0) add(x,y,z);
41     else if(x->f>0&&y->f<0) sub(x,y,z);
42     else sub(y,x,z);
43 }
44 void add(BigNum *x,BigNum *y,BigNum *z){
45     z->len=max(x->len,y->len);
46     for(int i=1;i<=z->len;i++){
47         z->s[i]+=x->s[i]+y->s[i];
48         z->s[i+1]=z->s[i]/10;
49         z->s[i]%=10;
50     }
51     if(z->s[z->len+1]) z->len++;
52 }
53 void subtract(BigNum *x,BigNum *y,BigNum *z){//符号确定后差的值就是大数减小数 
54     for(int i=1;i<=x->len;i++){
55          z->s[i]=x->s[i]-y->s[i];
56         if(z->s[i]<0){
57             x->s[i+1]--;
58             z->s[i]+=10;
59         }
60     }
61     int o=x->len;
62     while(o>1&&!z->s[o]) o--;
63     z->len=o;
64 }
65 void sub(BigNum *x,BigNum *y,BigNum *z){//判断差的符号 
66     if(x->len<y->len){
67         z->f=-1;
68         subtract(y,x,z);
69     }
70     else if(x->len==y->len){
71         for(int i=x->len;i>0;i--)
72           if(x->s[i]<y->s[i]){
73               z->f=-1;
74               subtract(y,x,z);
75               return;
76           }
77         subtract(x,y,z);
78     }
79     else subtract(x,y,z);
80 }
真高精度加法

 

posted @ 2017-11-04 17:25  lpl_bys  阅读(234)  评论(0编辑  收藏  举报