zoukankan      html  css  js  c++  java
  • 高精度加、减及混合

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

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

    一步一步来吧!

    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 }
    真高精度加法
  • 相关阅读:
    洛谷 P4484
    洛谷 P4900
    Codeforces 1500D
    Codeforces 1322D
    2021.9.30 Codeforces 中档题四道
    BZOJ 3729
    洛谷 P6276
    Codeforces 1511G
    C语言 typedef
    C语言 回调函数 callback
  • 原文地址:https://www.cnblogs.com/lpl-bys/p/7783939.html
Copyright © 2011-2022 走看看