C語言程序設計100例之(67):大整數加法


例67  大整數加法

問題描述

求兩個不超過200位的非負整數的和。

輸入

有兩行,每行是一個不超過200位的非負整數,可能有多余的前導0。

輸出

一行,即相加后的結果。結果里不能有多余的前導0,即如果結果是342,那么就不能輸出為0342。

輸入樣例

22222222222222222222

33333333333333333333

輸出樣例

55555555555555555555

        (1)編程思路。

        可以用一個字符串來保存200位整數。

        編寫函數void add(char *a,char *b,char *c)實現大整數c=a+b。

        在函數中可以用數組unsigned x[201]來保存一個200 位的整數a,讓x[0]存放個位數,x[1]存放十位數,x[2]存放百位數……。

        實現兩個大整數相加的方法很簡單,就是模擬小學生列豎式做加法,從個位開始逐位相加,超過或達到10 則進位。

(2)源程序。

#include <stdio.h>

#include <string.h>

void add(char *a,char *b,char *c)

{

    int len1=strlen(a),len2=strlen(b);

    int x[201],y[201],z[205];

    int len=len1>len2?len1:len2;

    memset(x,0,sizeof(x));

    memset(y,0,sizeof(y));

    memset(z,0,sizeof(z));

    int i;

    for (i=len1-1;i>=0;i--)

        x[len1-1-i]=a[i]-'0';

    for (i=len2-1;i>=0;i--)

        y[len2-1-i]=b[i]-'0';

    int cf=0;

    for (i=0;i<len;i++)

    {

        z[i]=(x[i]+y[i]+cf)%10;

        cf=(x[i]+y[i]+cf)/10;

    }

    z[len++]=cf;

    while (len>0 && z[len-1]==0) // 去前置0

        len--;

    if (len==0)  // a+b=0時特判

    {

        c[0]='0';

        c[1]='\0';

        return ;

    }

    for (i=0;i<len;i++)

        c[i]=z[len-1-i]+'0';

    c[len]='\0';

}

int main()

{

    char s1[201],s2[201],ans[205];

    scanf("%s%s",s1,s2);

    add(s1,s2,ans);

    printf("%s\n",ans);

    return 0;

}

習題67

67-1  二進制加法

問題描述

給出兩個二進制數a和b的01串,按二進制加法計算a+b並輸出。

輸入

第1行為一個整數T,表示測試用例的組數,之后T行,每行包括兩個01串,每個串長不超過80位。

輸出

對於每組測試用例,輸出兩個01串相加的結果(最簡形式)。

輸入樣例

3

1001101 10010

1001001 11001

1000111 1010110

輸出樣例

1 1011111

2 1100010

3 10011101

        (1)編程思路。

        二進制數高精度加法,注意前置0的處理。

       (2)源程序。

#include <stdio.h>

#include <string.h>

void binAdd(char *a,char *b,char *c)

{

    int len1=strlen(a),len2=strlen(b);

    int x[91],y[91],z[91];

    int len=len1>len2?len1:len2;

    memset(x,0,sizeof(x));

    memset(y,0,sizeof(y));

    memset(z,0,sizeof(z));

    int i;

    for (i=len1-1;i>=0;i--)

        x[len1-1-i]=a[i]-'0';

    for (i=len2-1;i>=0;i--)

        y[len2-1-i]=b[i]-'0';

    int cf=0;

    for (i=0;i<len;i++)

    {

        z[i]=(x[i]+y[i]+cf)%2;

        cf=(x[i]+y[i]+cf)/2;

    }

    z[len++]=cf;

    while (len>0 && z[len-1]==0)   // 去前置0

        len--;

    if (len==0)  // a+b=0時特判

    {

        c[0]='0';

        c[1]='\0';

        return ;

    }

    for (i=0;i<len;i++)

        c[i]=z[len-1-i]+'0';

    c[len]='\0';

}

int main()

{

    char s1[91],s2[91],ans[91];

    int n,i;

    scanf("%d",&n);

    for (i=1;i<=n;i++)

    {

        scanf("%s%s",s1,s2);

        binAdd(s1,s2,ans);

        printf("%d %s\n",i,ans);

    }

    return 0;

}

67-2  大整數減法

問題描述

求兩個大的正整數相減的差。

輸入

共2行,第1行是被減數a,第2行是減數b(a > b)。每個大整數不超過200位,不會有多余的前導零。

輸出

一行,即所求的差。

輸入樣例

9999999999999999999999999999999999999

9999999999999

輸出樣例

9999999999999999999999990000000000000

         (1)編程思路。

        可以用一個字符串來保存200位整數。

        編寫函數voidsub(char *a,char *b,char *c)實現大整數c=a-b。

        在函數中可以用數組unsigned x[201]來保存一個200 位的整數a,讓x[0]存放個位數,x[1]存放十位數,x[2]存放百位數……。

        實現兩個大整數相減的方法很簡單,就是模擬小學生列豎式做減法,從個位開始逐位相減,小於0則向前借位補10。

       (2)源程序。

#include <stdio.h>

#include <string.h>

void sub(char *a,char *b,char *c)

{

    int len1=strlen(a),len2=strlen(b);

    int x[210],y[210],z[210];

    int len=len1;

    memset(x,0,sizeof(x));

    memset(y,0,sizeof(y));

    memset(z,0,sizeof(z));

    int i,j;

    for (i=len1-1,j=0;i>=0;i--,j++)

        x[j]=a[i]-'0';

    for (i=len2-1,j=0;i>=0;i--,j++)

        y[j]=b[i]-'0';

    int cf=0;

    for (i=0;i<len;i++)

    {

              z[i]=x[i]-y[i]+cf;

              if (z[i]<0)

              {

                     z[i]+=10;

                     cf=-1;

              }

        else

                     cf=0;

       }

    while (len>0 && z[len-1]==0)   // 去前置0

        len--;

    if (len==0)    // a-b=0時特判

    {

        c[0]='0';

        c[1]='\0';

        return ;

    }

    for (i=0;i<len;i++)

        c[i]=z[len-1-i]+'0';

    c[len]='\0';

}

int main()

{

    char a[210],b[210],c[210];

    scanf("%s", a);

    scanf("%s", b);

    sub(a,b,c);

    printf("%s\n",c);

    return 0;

}

67-3  求和

問題描述

已知兩個整數a和b,求a+b的值

輸入

第一行包含一個整數T,即測試用例的數量。

以下T行,每行分別包含2個整數A、B(-10^50000<A、B<32768)。

輸出

輸出應該包含T行,每個行都有一個整數,代表相應的和。

輸入樣例

2

1 2

-1 +2

輸出樣例

3

1

        (1)編程思路。

        由於a和b可能小於0,因此a+b分為4種情況:

        1)a>=0,b>=0,則進行a+b;

        2)a<0,b<0,則進行(-a)+(-b);

        3)a>=0,b<0,則進行a-(-b);此時還需對a和(-b)進行大小比較,按比較情況執行a-(-b)或(-b)-a;

        4)3)a<0,b>=0,則進行b-(-a);此時還需對-a和b進行大小比較,按比較情況執行b-(-a)或(-a)-b。

       (2)源程序。

#include <stdio.h>

#include <string.h>

void add(char *a,char *b,char *c)

{

    int len1=strlen(a),len2=strlen(b);

    int x[51000],y[51000],z[51000];

    int len=len1>len2?len1:len2;

    memset(x,0,sizeof(x));

    memset(y,0,sizeof(y));

    memset(z,0,sizeof(z));

    int i;

    for (i=len1-1;i>=0;i--)

        x[len1-1-i]=a[i]-'0';

    for (i=len2-1;i>=0;i--)

        y[len2-1-i]=b[i]-'0';

    int cf=0;

    for (i=0;i<len;i++)

    {

        z[i]=(x[i]+y[i]+cf)%10;

        cf=(x[i]+y[i]+cf)/10;

    }

    z[len++]=cf;

    while (len>0 && z[len-1]==0) // 去前置0

        len--;

    if (len==0)  // a+b=0時特判

    {

        c[0]='0';

        c[1]='\0';

        return ;

    }

    for (i=0;i<len;i++)

        c[i]=z[len-1-i]+'0';

    c[len]='\0';

}

void sub(char *a,char *b,char *c)

{

    int len1=strlen(a),len2=strlen(b);

    int x[51000],y[51000],z[51000];

    int len=len1;

    memset(x,0,sizeof(x));

    memset(y,0,sizeof(y));

    memset(z,0,sizeof(z));

    int i;

    for (i=len1-1;i>=0;i--)

        x[len1-1-i]=a[i]-'0';

    for (i=len2-1;i>=0;i--)

        y[len2-1-i]=b[i]-'0';

    int cf=0;

    for (i=0;i<len;i++)

    {

              z[i]=x[i]-y[i]+cf;

              if (z[i]<0)

              {

                     z[i]+=10;

                     cf=-1;

              }

              else

                     cf=0;

       }

    while (len>0 && z[len-1]==0) // 去前置0

        len--;

    if (len==0)  // a-b=0時特判

    {

        c[0]='0';

        c[1]='\0';

        return ;

    }

    for (i=0;i<len;i++)

        c[i]=z[len-1-i]+'0';

    c[len]='\0';

}

int bigger(char *a,char *b)

{

    if (strlen(a)>strlen(b)) return 1;

    if (strlen(a)<strlen(b)) return 0;

    if (strcmp(a,b)>=0) return 1;

    else return 0;

}

int main()

{

    int t;

       scanf("%d",&t);

       while(t--)

      {

              char a[51000],b[51000],ans[51000];

              scanf("%s%s",a,b);

              if (a[0]=='+') strcpy(a,&a[1]);

              if (b[0]=='+') strcpy(b,&b[1]);

              int sign;

              if (a[0]!='-' && b[0]!='-')       // a+b

              {

                   add(a,b,ans);

                  sign=0;

              }

              else if (a[0]=='-' && b[0]=='-')  // -a-b=-(a+b)

              {

                     add(&a[1],&b[1],ans);

                     sign=1;

              }

              else if (a[0]!='-' && b[0]=='-')  // a-b

              {

                     if (bigger(a,&b[1]))

                     {

                sub(a,&b[1],ans);

                sign=0;

     }

                     else                 // b>a,a-b=-(b-a)

                     {

                            sub(&b[1],a,ans);

                            sign=1;

                     }

              }

              else                    // b-a

             {

                     if (bigger(b,&a[1])) // b>a

                     {

                            sub(b,&a[1],ans);

                            sign=0;

                     }

                     else                // b<a,b-a=-(a-b)

                    {

                          sub(&a[1],b,ans);

                          sign=1;

                    }

              }

              if (sign==1 && ans[0]!='0') printf("-");

              printf("%s\n",ans);

       }

       return 0;

}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM