编程学习笔记3--大整数的运算

本来是打算写四种大整数的计算的,但是除法没有成功,因为当初只看到了题目里面求加法的计算,突发奇想准备把四种都写处出来,但是一开始的时候没有考虑到除法会用到减法,函数运行一直出错,以后思考了,先放过去了大笑


题目当时要求计算长的整数的加法,数据为比较多的,其实无非就是不能直接用一个变量存储的整数的运算。

感悟:奋斗大数据的处理,感觉就是考察对数组的运用,加法和减法的处理是比较简单的,但是乘法和除法的处理就需要很强的技巧了。除法的自己还没有想好哭


#include<stdio.h>
#include<string.h>
/**计算数字长度少于200内的乘法*/
#define M 200
/**这些都是一些全局数组,当时只是写了加法,其他的都是后来一时有兴趣写的,所以没有把数组放到函数里面。
而且数组这么大,放进去不太好*/
char op_1[M+1]={0};
char op_2[M+1]={0};
char result[2*(M+1)]={0};//积的位数最多为乘数中位数较大的二倍


char result_div[2*(M+1)]={'0'};
char div_tem[M+1]="1";
/**对两个数加减的时候,位数不想等的时候要保证又对齐,不论什么情况都是从右向左操作的,为了防止数组向左
越界,必须处理,可以每次都在程序判断哪一个存储数据的数组下标到0了,到0后就加0,也可以上来就把两个补齐
变成一样长的,以后不用处理了。*/
int init(char*add_1,char *add_2)
{
    int i=0,off;
   if(strlen(add_1)>strlen(add_2))
   {
       off=strlen(add_1)-strlen(add_2);
       for(i=strlen(add_2)-1;i>=0;i--)
       {
           add_2[i+off]=add_2[i];
       }
       for(i=0;i<off;i++)
       {
           add_2[i]='0';
       }
   }
   if(strlen(add_2)>strlen(add_1))
   {
       off=strlen(add_2)-strlen(add_1);
       for(i=strlen(add_1)-1;i>=0;i--)
       {
           add_1[i+off]=add_1[i];
       }
       for(i=0;i<off;i++)
       {
           add_1[i]='0';
       }
   }
   return strlen(add_2);
}
/**加法很好求,就是小学生竖式运算,按步骤来就行*/
void calculate_add(char*add_1,char *add_2)
{
   int r=0,i,j,len;
   len=init(add_1,add_2)-1;
   for(i=len,j=0,r=0;i>=0;i--,j++)
   {
       result[j]=(add_1[i]-'0'+add_2[i]-'0'+r)%10+'0';
       r=(add_1[i]-'0'+add_2[i]-'0'+r)/10;
   }
   if(r!=0)
   result[j]=r+'0';
}
/**减法很加法没有什么区别,无法就是一个负数,先根据补齐后的数组第一位的大小就可以判断大小,然后运算
最后决定加不加负号就可以了*/
void calculate_sub(char*Sub_1,char *Sub_2)
{
    int i,j,len,r=0,flag=0;
    char *sub_1,*sub_2;
    len=init(Sub_1,Sub_2)-1;
    if(Sub_1[0]<Sub_2[0])/***第一处*/
    {
        sub_2=Sub_1;
        sub_1=Sub_2;
        flag=1;
    }
    else
    {
        sub_1=Sub_1;
        sub_2=Sub_2;
    }
    for(i=len,j=0,r=0;i>=0;i--,j++)
    {
        if(sub_1[i]>=sub_2[i])
        {
            result[j]=sub_1[i]-sub_2[i]+'0';
        }
        else
        {
            if(sub_1[i]==('0'-1))//被借位前是0的情况
            {
                result[j]='9'-sub_2[i]+'0';
            }
            else
            {
                 result[j]=10+sub_1[i]-sub_2[i]+'0';
            }
            sub_1[i-1]=sub_1[i-1]-1;/**第一处保证这里不会越界小于0*/

        }
    }
    if(result[j-1]=='0')//这里不同与加法的判断,加法可能出现比加数多一位的情况,所以是对result[j]做判断
    result[j-1]='\0';//减法不会,所以对j-1进行操作,要的是消除多余的0
    if(flag==1)//负号是附加信息,应该在前面所有操作完成后进行决定添加与否
    result[strlen(result)]='-';
}
/**乘法本来想安装现实那样计算,但是如果真的按照现实计算需要一个很大的二维数组,浪费空间严重不说,
而且要最后对数组的每一行进行错位累加,感觉很麻烦。时间空间都比较浪费。所以自己分析了下过程,每次计算都
进行错位累加,即节省了时间也节省了空间*/
void calculate_mul(char *mul_1,char *mul_2)
{
    int i,j,k=0,off=-1,r=0;
    int temp0;
    for(i=strlen(mul_2)-1;i>=0;i--)
    {
        r=0;//进位的数值设置为0
        off++;//偏移量每次都要加1,模拟手动计算的时候的每次错一位
        k=0;
        for(j=strlen(mul_1)-1;j>=0;j--)
        {
           if(result[k+off]==0)//数组原来的值没有变
            {
                result[k+off]=((mul_1[j]-'0')*(mul_2[i]-'0')+r)%10+'0';//计算
                r=((mul_1[j]-'0')*(mul_2[i]-'0')+r)/10;
            }
            else//进行错位加法计算
            {
                temp0=result[k+off]-'0';
                 result[k+off]=(result[k+off]-'0'+(mul_1[j]-'0')*(mul_2[i]-'0')+r)%10+'0';
                 r=(temp0+(mul_1[j]-'0')*(mul_2[i]-'0')+r)/10;
            }
            k++;
        }
        if(r!=0)
        {
            result[k+off]='0'+r;
        }
    }
}
/**除法就没有那么好运了,想不出类似乘法的办法,本来想用现实那样进行试除,感觉那样运算不好。
下面是打算进行用第一个数减去第二个数,计算减到负数的次数。就是结果,但是没有成功啊!!感觉这样
其实效率也很低,每次都进行加1,数据特别大的时候时间肯定超时了,这种方法其实也不好*/
int calculate_div(char *div_1,char *div_2)
{
   int i,k=0;
   memset(result,0,sizeof(result));
   calculate_sub(div_1,div_2);
   if(result[strlen(result)-1]=='-')//第一个数比第二个数小的时候
   {
       result[0]='0';
       result[1]='\0';
       return 1;
   }
   for(i=strlen(result)-1;i>=0;i--)//帮刚刚做的减法操作的result里的结果保存到div_1
   {
        div_1[k++]=result[i];
   }
   div_1[k]='\0';//不能忘记了结束标志

   memset(result,0,sizeof(result));
   calculate_add(result_div,div_tem);//因为上面不为0,所以要进行一次加一。
   k=0;
   for(i=strlen(result)-1;i>=0;i--)//帮刚刚做的减法操作的result里的结果保存到result_div
   {
        result_div[k++]=result[i];
   }
   result_div[k]='\0';
   while(result[strlen(result)-1]!='-')
   {
       k=0;
       memset(result,0,sizeof(result));//使用前要清零
       calculate_sub(div_1,div_2);
       for(i=strlen(result)-1;i>=0;i--)
       {
            div_1[k++]=result[i];
       }
       div_1[k]='\0';//不能忘记了结束标志
       memset(result,0,sizeof(result));
       calculate_add(result_div,div_tem);
       k=0;
       for(i=strlen(result)-1;i>=0;i--)
       {
            result_div[k++]=result[i];
       }
        result_div[k]='\0';
   }

}
int main()
{
    int i;
    printf("请输入第一个数:\n");
    gets(op_1);
    printf("请输入第二个数:\n");
    gets(op_2);

    /**四种运算选择一个,做测试还是成功的*/
      //calculate_add(op_1,op_2);
     // calculate_sub(op_1,op_2);
      calculate_mul(op_1,op_2);

    for(i=strlen(result)-1;i>=0;i--)
    {
        putchar(result[i]);
    }
    return 0;

}<span style="font-weight: bold;">
</span>

乘法的截图





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值