大数加法分析及C语言实现(加数可为负数)

大数加法(加数可为负数)


·分析:

大数加法有如下几种情况:
1.两数同号
(1)同正:如,s1=11,s2=22;s1=0,s2=0
(2)同负:如,s1=-11,s2=-22
2.两数异号
(1)正数加负数:如,s1=11,s2=-9
  1)s1的长度大于s2绝对值的长度:如,s1=11,s2=-9
  2)s1和s2绝对值的长度相等但s1大于等于s2的绝对值:s1=106,s2=-104;s1=11,s2=-11
  3)s1的长度小于s2绝对值的长度:如,s1=9,s2=-11
  2)s1和s2绝对值的长度相等但s1小于s2的绝对值:s1=104,s2=-106
(2)负数加正数:如,s1=-9,s2=11
    位置转换可变换为“正数加负数”形式


处理:

首先,将大数以字符串形式输入
其次,判断s1与s2符号,调用不同函数处理
(1)同号:调用Plus函数
   1)如果同正,设置标志结果符号的flag为0,将两个字符串转化为数组形式倒序存储
   2)如果同负,设置标志结果符号的flag为1,将两个字符串转化为数组形式倒序存储,但不存储两字符串的第0位(因为第0位为负号)
   3)将两数组对应位相加,位数满10进1
   4)根据flag值输出结果的符号
   5)判断最高位是否为0,输出结果数组
(2)异号:调用Minus函数
   1)调用函数时以正数-负数顺序传递实参给形参,即s1为正数,s2为负数
   2)将两个字符串转化为数组形式倒序存储,但不存储s2字符串的第0位(因为s2[0]为负号)
   3)判断结果符号,根据两数大小,有两种情况:
     1)s1的长度大于s2的长度或s1和s2长度相等但s1大于等于s2,即:
           len1>(len2-1) 或 len1==(len2-1),s1>=s2 做num1-num2,设置flag=0,标志得正数
     2)s1的长度小于s2的长度或s1和s2长度相等但s1小于s2,即:
           len1<(len2-1)或 len1==(len2-1),s1<s2 做num2-num1,设置flag=1,标志得负数
     3)调用Minus_show函数
           - 对传进来的num1-num2或num2-num1做减法计算
           - 将两数组对应位相减,位数不够减向前借1
           - 根据flag值输出结果的符号
           - 判断最高位是否为0,输出结果数组


实现:

#include<stdio.h>
#include<string.h>
char s1[10005],s2[10005],s3[10005];
int num1[10005],num2[10005];
int len1,len2,i,j;

//当s1与s2同号,利用flag标志结果的符号(0为正,1为负)
void Plus(int flag)
{
    len1=strlen(s1);
    len2=strlen(s2);
    for(i=len1-1,j=0; i>=0 ; i--)
    {
        num1[j]=s1[i]-48;
        j++;
        if(i==flag) break; //如果s1与s2同负,flag=1,则不进行下一次循环赋值字符串第0位
    }
    for(i=len2-1,j=0; i>=0 ; i--)
    {
        num2[j]=s2[i]-48;
        j++;
        if(i==flag) break; //如果s1与s2同负,flag=1,则不进行下一次循环赋值字符串第0位
    }

    //计算两字符串长度最大值作为和的长度
    int len;
    if(flag==0) len=len2>len1?len2:len1;
    else len=len2>len1?(len2-1):(len1-1); //如果s1与s2同负,flag=1,len值应为长度减1

    //进行加计算及进位
    for(i=0; i<len; i++)
    {
        num1[i]+=num2[i];
        if(num1[i]>9)
        {
            num1[i+1]+=1;
            num1[i]-=10;
        }
    }

    //输出符号位
    if(flag==1) printf("-"); //如果s1与s2同负,flag=1,结果的符号位为负
    //输出结果
    if(num1[i]) //最高位进位
    {
        for(j=i; j>=0; j--)
            printf("%d",num1[j]);
        printf("\n");
    }
    else        //最高位未进位
    {
        for(j=i-1; j>=0; j--)
            printf("%d",num1[j]);
        printf("\n");
    }
}

//对异号的s1和s2处理成“大数-小数”形式后调用该函数进行减计算并显示,利用flag标志结果的符号(0为正,1为负)
void Minus_show(int flag,int len,int num1[],int num2[])
{
    //进行减计算及借位
    for(i=0; i<len; i++)
    {
        if(num1[i]>=num2[i])
        {
            num1[i]-=num2[i];
        }
        else
        {
            num1[i]=num1[i]+10-num2[i];
            num1[i+1]-=1;
        }
    }

    //输出过滤掉结果前面无效的0
    while(num1[--i]==0)
    {
        if(i==0) break;
    }

    //输出符号位
    if(flag==1) printf("-");  //flag=1,结果的符号位为负
    //输出结果
    for(j=i; j>=0; j--)
        printf("%d",num1[j]);
    printf("\n");
}
//当s1与s2异号,以正数-负数顺序传递实参给形参
void Minus(char s1[],char s2[])
{
    len1=strlen(s1);
    len2=strlen(s2);
    for(i=len1-1,j=0; i>=0 ; i--)  //s1为正数
    {
        num1[j]=s1[i]-48;
        j++;
    }
    for(i=len2-1,j=0; i>0 ; i--)  //s2为负数,s2[0]为符号位,不要
    {
        num2[j]=s2[i]-48;
        j++;
    }

    memset(s3,0,sizeof(s3)); //为了便于比较同长度下的两个数的大小,将去掉负号的s2赋值给s3
    for(i=1,j=0; i<len2; i++)
    {
        s3[j++]=s2[i];
    }

    //【3】 对应计算例子:(1)s1=11,s2=-9 ;(2)s1=106,s2=-104;(3)s1=11,s2=-11
    //len1>(len2-1) 或 len1==(len2-1),s1>=s2 做num1-num2,设置flag=0,标志得正数
    if(len1>(len2-1)||(len1==(len2-1)&&strcmp(s1,s3)==0)||len1==(len2-1)&&strcmp(s1,s3)==1)
    {
        Minus_show(0,len1,num1,num2);
    }

    //【4】对应计算例子:(1)s1=9,s2=-11 ;(2)s1=104,s2=-106
    //(len2-1)>len1 或 len1==(len2-1),s1<s2  做num2-num1,设置flag=1,标志得负数
    else if((len2-1)>len1||(len1==(len2-1)&&strcmp(s1,s3)==-1))
    {
        Minus_show(1,len2-1,num2,num1);
    }
}
int main()
{
    while(1)
    {
        //printf("please intput numbers:\n");
        scanf("%s%s",s1,s2);
        memset(num1,0,sizeof(num1));
        memset(num2,0,sizeof(num2));

        //【1】对应计算例子:(1)s1=11,s2=22;(2)s1=0,s2=0
        if(s1[0]!='-'&&s2[0]!='-')
        {
            Plus(0); //s1与s2同正,设置flag=0
        }
        //【2】对应计算例子:(1)s1=-11,s2=-22
        else if(s1[0]=='-'&&s2[0]=='-')
        {
            Plus(1); //s1与s2同负,设置flag=1
        }
        //【3】对应计算例子:s1=11,s2=-9
        else if(s1[0]!='-'&&s2[0]=='-')
        {
            Minus(s1,s2); //s1为正,s2为负,传递s1,s2顺序,实现一个正数减一个负数
        }
        //【4】对应计算例子:s1=-9,s2=11
        else
        {
            Minus(s2,s1); //s1为正,s2为负,传递s2,s1顺序,实现一个正数减一个负数
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/ccchenxi/article/details/84975050
今日推荐