高精度加法

A + B Problem II

 

I have a very simple problem for you. Given two integers A and B, your job is to calculate the Sum of A + B.

 

Input
    The first line of the input contains an integer T(1<=T<=20) which means the number of test cases. Then T lines follow, each line consists of two positive integers, A and B. Notice that the integers are very large, that means you should not process them by using 32-bit integer. You may assume the length of each integer will not exceed 1000.
Output

    For each test case, you should output two lines. The first line is "Case #:", # means the number of the test case. The second line is the an equation "A + B = Sum", Sum means the result of A + B. Note there are some spaces int the equation. Output a blank line between two test cases.

 

Sample Input

    2
    1 2
    112233445566778899 998877665544332211

Sample Output

    Case 1:
    1 + 2 = 3

    Case 2:
    112233445566778899 + 998877665544332211 = 1111111111111111110


这道题其实就是求一个高精度加法的问题,很简单,关键还是要对高精度算法有清晰明确的理解。

下面我们先来说一说高精度算法:

高精度存在的意义是什么呢?说白了就是为了运算大数据,众所周知,c/c++里面定义数据类型最大的,也就是使用long long型,那也只能存放64位二进制数,那如果遇到如题示例中的超大数据就无能为力,只能望洋兴叹了。。。

这时候该如何处理呢。。。一般武侠玄幻小说里面都会说到一个词,一旦提到这个词的人物莫不是狂拽酷无敌屌炸天,这个词呢就是:返璞归真。我们学习之路也是需要一个返璞归真的过程的。大家还记得我们在小学初学计算加法时的方法吗?竖式算法,这是最基础但也是最好用的方法,因为它的包罗万象,有它在我们可以计算任何我们想要的数据。

那我们是不是可以设计程序,让电脑按照这种方式运算呢。于是在人类无穷探索力之下,高精度算法诞生了。

我们先来复习一下竖式计算:

                      1 2 3 4 5 6 7 8 9

        + 9 8 7 6 5 4 3 2 1

———————————————

        1 1 1 1 1 1 1 1 1 0


我们既然没有足够大的数据类型去存放这两个数据,那该怎么让计算机识别这个数据呢,这时候我们就应该用char数组去存储数据了。为什么是char而不是int呢,因为char的大小比较适合。

接下来我们会发现竖式运算是右对齐的,同时也是从右边开始运算的,但是我们不知道输入数据的长度,这时候我们该怎么办呢?其实很简单,我们可以直接将数组倒置,也就是让a[0]为输入数据的最后一位,这样虽然不了解数据的长度,但我们只要从0开始依次向后就好。
 

接下来我们需要做一件很容易忽略的事,毕竟我们定义的是char,如果我们输出的ans是int型,那么我们在倒置数组的时候,还有一件事要一并完成。那就是(-'0'),也就是减去0的ASCII码,即-48,这样一来我们就可以让数据本身等于本身,也就是本来0字符串在整型里代表的是48,在我减去‘0’最后,0字符串代表的就是0本身了。这样操作我们在输出的时候就可以很方便的表达。

然而你以为这样就可以高枕无忧了吗?大错特错!题目在这里设置了一个巨型天坑,那就是输入的数据竟然会有前置零!就是会有类似001这样的数,好恼火有没有!这个点很简单就可以处理掉了,关键就是要get到它啊。。。。具体处理方法就是用strlen函数计算出数据长度,从最后一位开始,直到遇到第一个不为零的数,遇到一个零就让总长度减1,一直减一直减,这样就可以去除前置0的影响了。

为了获得答案,首先我们需要知道答案的长度,这个计算机显然是无法判断的,但我们知道一点,那就是既然是加法,答案的长度就绝对不会小于其中的任意一个数的长度,所以我们先让答案的长度等于较长的个该加数的长度,具体的操作我们下面再说。

现在知道了answer的长度len(暂时),我们就该进行竖式算法的加减了,到了这里其实反而最简单了,我们只要令ans[i]=a[i]+b[i],再判断ans[i]时候超过十,如果超过了,我们直接让ans[i+1]+=1;这样循环,介于答案长度到这里也就不言而喻了,当ans[len-1]大于10的时候,就说明需要改变长度了,只要让len++就ok了。

这时候还有一个特例需要解决,就是当数据是0 0是,我们会把数据当做前置0全部去掉,这时候输入数据长度就是0,我们需要加上len==0时,输出‘0’这样一个操作就ok,

最后输出结果一个循环就行,因为前面我们已经进行过-‘0’操作,放心大胆的输出%d,答案一定没毛病。

最后因为是多住组输入,我们在输出结果后还需要对三个数组进行清零,我推荐使用memset函数,方便合适,实在是清理数组,必备良药。

回头看来,高精度加法也不过如此,上代码:

/*high accuracy'+'*/
#include<iostream>
#include<string.h>
#include<stdio.h>
using namespace std;
const int m=1e3;
int s[m]={0};
void strchange( char str[],int l )
{    
    for( int i=0;i<(l+1)/2;i++ )
    {    if( i!=l-i-1 )
        str[i]-=48;
        str[l-i-1]-=48;//字符型情况下
        int t;
        t=str[i];
        str[i]=str[l-i-1];
        str[l-i-1]=t;
    }
}//数组反转

int main()
{
    long long la,lb,ls;
    char a[1050],b[1050];
    while( scanf("%s %s",&a,&b)!=EOF )
    {
        la=strlen(a);
        lb=strlen(b);
        strchange(a,la);
        strchange(b,lb);
        /*去除前置0*/
        for( int i=la-1;a[i]==0&&i>=0;i-- )
        la-=1;
        for( int i=lb-1;b[i]==0&&i>=0;i-- )
        lb-=1;
        ls=la>lb?la:lb;

        for( int i=0;i<ls;i++ )
        {
 
        s[i]+=a[i]+b[i];
        if( s[i]>9 ){
        s[i+1]+=1;
        s[i]=s[i]%10;
        if(i==ls-1)
        ls++;
        }
//        printf("%d ",s[i]);
//        printf("%ds\n",s[i]);
//        printf("%dls",ls);
    }
    if(ls==0)
    {
        printf("0\n");
        continue;
    }
    for( int i=ls-1;i>=0;i-- )
    printf("%d",s[i]);
    printf("\n");
    memset(s,0, sizeof(s));
    memset(a,0, sizeof(a));
    memset(b,0, sizeof(b));
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值