a+b高精度



高精度之旅

                     ---by ysmor

               ---本文为作者原创,请勿转载

   c++编程时,系统本来是带有运算符+-*/%的。但是,这些运算符也不是万能的。他们最多也就算个long long int 范围的加法罢了。但是,如果来一个10000位的数字加10000位的数字怎么办?

   如果还用+号的话,系统就开始打乱码了。于是,一个人就发明了高精度算法。

高精度算法简介

   高精度算法,属于处理大数字的数学计算方法。在一般的科学计算中,会经常算到小数点后几百位或者更多,当然也可能是几千亿几百亿的大数字。一般这类数字我们统称为高精度数,高精度算法是用计算机对于超大数据的一种模拟加,减,乘,除,乘方阶乘,开方等运算。对于非常庞大的数字无法在计算机中正常存储,于是,将这个数字拆开,拆成一位一位的,或者是四位四位的存储到一个数组中,用一个数组去表示一个数字,这样这个数字就被称为是高精度数。高精度算法就是能处理高精度数各种运算的算法,但又因其特殊性,故从普通数的算法中分离,自成一家。

----摘自百度百科

   如果你要看不明白,那么我总结一下,就是把两个数通过计算机模拟生活中我们手算加法,像列竖式一样。

PS:不会有人不会列竖式吧!!!T_T

   所以,正题开始了。。。。。。

 

 

   首先,先想想这几个数的类型。intlong long int肯定不行。10000位呢。所以,我们可以用字符串string来解决这个问题。

PS:如果你的dev-c++的版本比较久的话,请加入头文件#include<cstring>

   所以,基本程序如下

#include<iostream>

using namespace std;

int main()

{

    string str1,str2,str3;

    cin>>str1>>str2;

    int len1=str1.length(),len2=str2.length();

 

/*

首先,介绍一下字符串:字符串和字符数组(char a[])一样,都可以用cin>>输入。str1,str2用来输入,而str3用来表示结果。

接着是len1,len2。这两个数用来表示字符串str1,str2的长度。

函数.lenth()表示测一个字符数组的长。例:str1.lenth()表示字符串str1

的长度。*/

20130129151009977_02.jpg

   如上图,这是一个加法竖式。虽然简单,但可以解释我们的程序。我们的竖式都是从最后一位开始算起的。如果有进位的话,可以进到下一位。

   所以,据此我们采用反码来计算。所谓反码,就是把输入的数倒过来,这样的话,就可以从第一位开始,一位一位的算了。

   对啦,忘说了,再定义一个jw代表进位。当进位时,把jw定义成进位的那个数,下次使用。

   以下为反码所用的代码:

for(int i=0;i<len1/2;i++)swap(str1[i],str1[len1-i-1]);

for(int i=0;i<len2/2;i++)swap(str2[i],str2[len2-i-1]);

   这样的话,我们就把正常的字符串转换成它的反码了。

   解释一下,str1[i]代表前面的数,str1[len1-i-1]则是str1[i]所对应的反码。swap(a,b)代表交换a,b的值。这样的话,就把整个字符串都反过来了。

   例如输入1234;它的反序就是4321

 

 

   然后判断一下长短。如果str1str2短,那么交换它们

   代码:

if(len1<len2)

{

    for(int i=0;i<len2;i++)swap(str1[i],str2[i]);

    swap(len1,len2);

}

 

这样就确定str1str2大了。

接下来是最精彩的部分:模拟手算竖式。先给代码:

 

int jw=0; 
    for(int i=0;i<len2;i++)

    {

        if(i<len1)

        {

            str3[i]=(str1[i]+str2[i]-'0'-'0'+jw)%10+'0';

            jw=(str1[i]+str2[i]-'0'-'0'+jw)/10;

        }

        else if(i>=len1&&i<len2)

        {

            str3[i]=(str2[i]-'0'+jw)%10+'0';

            jw=(str2[i]-'0'+jw)/10;

        }

    }

    if(jw!=0)cout<<jw;

    for(int i=len2-1;i>=0;i--)cout<<str3[i];

    system("pause");

    return 0;

}

return 0;

int jw=0;//这个刚才说过,定义的进位;

for(int i=0;i<len2;i++)

/*这个就是开始运算,从最后一位(刚才已经把它换为反码了)开始运算,跟最长的字符串一样长。*/

       if(i<len1)

        {

            str3[i]=(str1[i]+str2[i]-'0'-'0'+jw)%10+'0';

            jw=(str1[i]+str2[i]-'0'-'0'+jw)/10;

        }

        else if(i>=len1&&i<len2)

        {

            str3[i]=(str2[i]-'0'+jw)%10+'0';

            jw=(str2[i]-'0'+jw)/10;

        }

/*我想这句话可以好好讲讲:str3[i]为结果的第i位。

写得仔细一些,这句话可以拆成:

str3[i]=((str1[i] -'0')+(str2[i] -'0')+jw)%10+'0';

    首先,str1[i]-'0'表示小的那个字符串的第i位。因为str1[i]为char形式,所以由ascii码可知,用它减一个字符'0'就可以得到他的int形式了。

    同理,str2[i]-'0'表示大的字符串的第i位。

    为什么要加jw?这里,因为是循环,所以jw是表示上一位的进位。加上才能表示这一位。%10表示这位万一要进位,就可以通过这种方法来确定这位是什么。

    所以,按理说这已经算完了。但,不要忘记str3是字符串,所以要返回的是字符,所以不要忘记加上一个字符'0'。

    但是,为什么开始会有一个if?

    现在解释:当i<len1时,有两个数相加,所以是str1[i]+str2[i];

当i>=len1时,只有str2一个数自己加进位了,所以不用考虑str1[i];

*/

jw=(str1[i]+str2[i]-'0'-'0'+jw)/10;

/*

这段表示的是新一次进位。因为int在除以10的时候,如果除不尽,小数点后的所有都抹了。所以用这个来计算进位。这样返回的就是进位了。

*/

主体结构已经讲完,接下来就是输出。在输出前,有一个很重要的事情,就是先考虑最后一次进位。如果进位是0;就不用输出,不是零就输出。所以判断一下。

if(jw!=0)cout<<jw;

for(int i=len2-1;i>=0;i--)cout<<str3[i];

最后循环输出结果即可。

以下为正确代码:

正确代码:

#include<iostream>

using namespace std;

int main()

{

    char str1[10001],str2[10001],str3[10001];

    cin>>str1>>str2;

    int len1=strlen(str1),len2=strlen(str2);

    if(len1>len2)

    {

        for(int i=0;i<len1;i++)swap(str1[i],str2[i]);

        swap(len1,len2);

    }

    for(int i=0;i<len1/2;i++)swap(str1[i],str1[len1-i-1]);

    for(int i=0;i<len2/2;i++)swap(str2[i],str2[len2-i-1]);

    int jw=0;

    for(int i=0;i<len2;i++)

    {

        if(i<len1)

        {

            str3[i]=(str1[i]+str2[i]-'0'-'0'+jw)%10+'0';

            jw=(str1[i]+str2[i]-'0'-'0'+jw)/10;

        }

        else if(i>=len1&&i<len2)

        {

            str3[i]=(str2[i]-'0'+jw)%10+'0';

            jw=(str2[i]-'0'+jw)/10;

        }

    }

    if(jw!=0)cout<<jw;

    for(int i=len2-1;i>=0;i--)cout<<str3[i];

    system("pause");

    return 0;

}

感谢收看!!!

                                     by---ysmor

                                     2016.5.23

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值