大整数专题之大整数相加【附过程详解+两种方法+测试数据+例题】

大数问题,其实就是模拟运算,因为系统自带的int、long、bouble(double虽然可以表示很大的数,但那是使用的科学记数法,保存的数值的精度是有限的,最大精度只有十几位,后面的数字就保存不了了,会全变成0)这些类型均无法容纳百位乃至千位的大数字,从而手动模拟的运算过程,我们一般使用字符串来表示这样的超大数字。

测试数据:

/*
987654321987654321 987654321987654321
1975308643975308642

9999999999999999999 9
100000000000000000008
*/

基本上这两组测试数据过了就没啥问题了。

方法一:使用三个字符串【两个用于存储输入的待计算的大整数,一个用于过程计算中的临时存储】+一个整型数组【为了进位方便而设置的数组】

#include<stdio.h>
#include<string.h>
int main()
{
    int n,i,j,count=0,num1[1006],len1,len2,len_max,result,t;
    char str1[1006],str2[1006],str3[1006];
    scanf("%d",&n);
    while(n--)
    {
        memset(num1,0,sizeof(num1));//把整型数组清零
        scanf("%s %s",str1,str2);
        /*如果把它们看成整形数据,比如输入的是13和87,我们知道其结果是100
        现在我们是把他们看成字符串了,因此:
        对于13来说,str1[0]=1,str1[1]=3
        对于87来说,str2[0]=8,str2[1]=7
        我们在计算时,只需要按小学的数学知识,让他们从低位到高位,每一位进行相加即可,
        满十进一,比如3+7=10,那么我们可以把字符数组相加的数据存储在整型数组中,
        num1[0]=str[1]+str2[1]=3+7=10(注意是把字符数组倒序相加,因为字符数组下标最大的数字是个位)
        因为num1[0]的结果大于等于10,我们需要满十进一,
        操作方法为:num1[0]=num1[0]-1;
        num1[1]=num1[1]+1;(之前记得把num1中的元素全部清零)
        num1[1]=str1[0]+str2[0]=1+8=9,又因为个位满十进一,所以,num1[1]=num1[1]+1=10,这里十位有满十了
        所以需要向百位进一,具体进位方式,我就不写了吧,和个位进十位一样


        然而,那种两个数字的位数一样,还比较好办,对于两个数字位数不一样的怎么办呢,
        我们可以加0补齐嘛,然后就转化成了刚才两个数字位数一样的问题了。
        比如:12 和998,我们可以把12补成012,998就不变了,
        我们只需要把数字位数最短的那个数字的位数补成和数字位数最长的那个数字的位数一样就行了


        12 和998,我们知道结果是1010
        对于12说,str1[0]=1,str1[1]=2
        对于998来说,str2[0]=9,str2[1]=9,str2[2]=8
        在进行补0的时候,我们需要特别注意:对于12,千万不能把str[2]补成0,
        因为那样一补位的话,就把12变成了120了,
        我们可以再定义一个字符数组str3,先把str3[1]弄成0,然后再把str2中的每一个元素挨个复制到str3中就行了
        这样就达到把12补成012的目的了


        同时为了接下来的方便,我们补完0之后,可以把str3中的每一位元素,再挨个复制到str2中
        */
        len1=strlen(str1);
        len2=strlen(str2);
        /*for(i=0;i<len1;i++)//用于显示输入的数字,再转化成字符串之后,字符数组的下标与每一位数字的关系
        {
            printf("str1[%d]=%c\n",i,str1[i]);
        }
        putchar(10);//打印换行,换行的ASCII代码是10
        for(i=0;i<len2;i++)
        {
            printf("str2[%d]=%c\n",i,str2[i]);
        }*/
        if(len1>=len2)
        {
            result=1;//用于观测哪个数字位数比较长
            len_max=len1;
            for(i=len2,j=0;i<len_max;i++,j++)//先补零
            {
                str3[j]='0';
            }
            for(i=0;i<len2;i++,j++)//再把str2中的元素依次复制到补零位之后
            {
                str3[j]=str2[i];
            }
            for(i=0;i<len_max;i++)//为了后续方便,可以把str3里的元素再逐位全部转到str2里
            {
                str2[i]=str3[i];
            }
        }
        else
        {
            result=0;
            len_max=len2;
            for(i=len1,j=0;i<len_max;i++,j++)
            {
                str3[j]='0';
            }
            for(i=0;i<len1;i++,j++)
            {
                str3[j]=str1[i];
            }
            for(i=0;i<len_max;i++)
            {
                str1[i]=str3[i];
            }
        }
        len_max=len1>=len2?len1:len2;
        for(i=len_max-1,j=0;i>=0;i--,j++)
        {
            num1[j]=str1[i]-'0'+str2[i]-'0';//把字符数组中的元素从个位到最高位依次计算
        }
        for(j=0;j<len_max;j++)
        {
            if(num1[j]>=10)
            {
                num1[j+1]=num1[j+1]+1;//从个位到最高位依次排查,看是否有大于等于10的情况,
                num1[j]=num1[j]-10;//如果有,则满十进一
            }
        }
        if(num1[len_max])//判断是否最高位有满十进一的情况,如果有则显示结果,没有则不显示
        {//因为之前已经把num1中的所有元素全部清成0了,所以如果那两个数相加的最高位没有满十进一的话,
            printf("%d",num1[len_max]);//num1[len_max]这一位肯定是0,0在C语言中代表假,也就不会执行
        } //if判断体中的代码了
        for(j=len_max-1;j>=0;j--)//接着再逐位打印出来就行了
        {
            printf("%d",num1[j]);
        }
        printf("\n");
    }
}

方法二:使用两个字符串数组、两个整型数组

#include<stdio.h>
#include<string.h>
int main()
{
    int num1[1006],num2[1006],len1,len2,lenmax,i,j;
    char str1[1006],str2[1006];
    while(1)
    {
        scanf("%s %s",&str1,&str2);
        memset(num1,0,sizeof(num1));
        memset(num2,0,sizeof(num2));//先清零
        len1=strlen(str1);
        len2=strlen(str2);
        lenmax=len1>=len2?len1:len2;
        for(i=len1-1,j=0;i>=0;i--,j++)
        {
            num1[j]=str1[i]-'0';//将字符串反转并且转换为数字保存在整型数组中
        }
        for(i=len2-1,j=0;i>=0;i--,j++)
        {
            num2[j]=str2[i]-'0';//将字符串反转并且转换为数字保存在整型数组中
        }
        for(i=0;i<lenmax;i++)
        {
            num1[i]=num1[i]+num2[i];//相加
            if(num1[i]>=10)
            {
                num1[i]=num1[i]-10;//满十进一
                num1[i+1]+=1;
            }
        }
        if(num1[lenmax])//判断数字中最大的那个数字的最高位是否产生进位
        {
            printf("%d",num1[lenmax]);
        }
        for(i=lenmax-1;i>=0;i--)
        {
            printf("%d",num1[i]);
        }
        putchar(10);//打印换行,换行的ASCII编码为10
    }
}

例题一:1154: A + B Problem (X)【附大整数相加详解教程】

http://blog.csdn.net/coco56/article/details/79143475

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
密码学分为两类密码:对称密码和非对称密码。对称密码主要用于数据的加/解密,而非对称密码则主要用于认证、数字签名等场合。非对称密码在加密和解密时,是把加密的数据当作一个大的正整数来处理,这样就涉及到大整数的加、减、乘、除和指数运算等,同时,还需要对大整数进行输出。请采用相应的数据结构实现大整数的加、减、乘、除和指数运算,以及大整数的输入和输出。 【基本要求】 1.要求采用链表来实现大整数的存储和运算,不允许使用标准模板类的链表类(list)和函数。 同时要求可以从键盘输入大整数,也可以文件输入大整数大整数可以输出至显示器,也可以输出至文件。大整数的存储、运算和显示,可以同时支持二进制和十进制,但至少要支持十进制。大整数输出显示时,必须能清楚地表达出整数的位数。测试时,各种情况都需要测试,并上测试截图;要求测试例子要比较详尽,各种极限情况也要考虑到,测试的输出信息要详细易懂,表明各个功能的执行正确。 2.要求大整数的长度可以不受限制,即大整数的十进制位数不受限制,可以为十几位的整数,也可以为500多位的整数,甚至更长;大整数的运算和显示时,只需要考虑正的大整数。如果可能的话,请以秒为单位显示每次大整数运算的时间。 3.要求采用类的设计思路,不允许出现类以外的函数定义,但允许友元函数。主函数中只能出现类的成员函数的调用,不允许出现对其它函数的调用。 4.要求采用多文件方式:.h文件存储类的声明,.cpp文件存储类的实现,主函数main存储在另外一个单独的cpp文件中。如果采用类模板,则类的声明和实现都放在.h文件中。 5.不强制要求采用类模板,也不要求采用可视化窗口;要求源程序中有相应注释。 6.要求采用Visual C++ 6.0及以上版本进行调试。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

COCO56(徐可可)

建议微信红包:xucoco56

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值